From 4bace1d565a6921e744acfeb3a8feea6d3c45ca6 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Sun, 6 Dec 2009 10:34:05 +0000 Subject: [PATCH] Merged from trunk -r14926:14936 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit | 14927 | Always append QA Notices resulting from the build log search | | zmedico | to the end of the log. Thanks to Diego E. Pettenò for | | | reporting. | | 14928 | Bug #162404 - Automatically disable logging if sesandbox is | | zmedico | enabled and a pty is not available for some reason | | | (currently they are never available with python3). | | 14929 | Bug #295805 - Fix ValueError with python3 inside | | zmedico | update_config_files(). | | 14930 | Move code for handling missing sandbox binary out of the | | zmedico | config constructor. | | 14931 | Use portage.StringIO to avoid duplicate import fallback | | zmedico | code. | | 14932 | Make register_die_hook() ensure that each hook is registered | | zmedico | only once. | | 14933 | Add a AbstractEbuildProcess class for MiscFunctionsProcess | | zmedico | to inherit the _pipe and _can_log methods that used to be in | | | the EbuildProcess class. | | 14934 | Fix _spawn_misc_sh() to properly unset EBUILD_PHASE, and add | | zmedico | a 'phase' description parameter for use in messages. | | 14935 | Add 'tla' to the lists of live eclasses. | | zmedico | | | 14936 | Bug #295715 - Implement a register_success_hook function to | | zmedico | complement register_die_hook, and also add code to ensure | | | the die hooks are called even when the failure is on the | | | python side (like for file collisions). | svn path=/main/branches/prefix/; revision=14940 --- bin/ebuild.sh | 17 ++++- bin/isolated-functions.sh | 1 + bin/misc-functions.sh | 16 +++++ bin/repoman | 3 +- cnf/sets.conf | 2 +- man/ebuild.5 | 11 ++++ pym/_emerge/AbstractEbuildProcess.py | 24 +++++++ pym/_emerge/EbuildBuild.py | 28 +++++--- pym/_emerge/EbuildExecuter.py | 3 +- pym/_emerge/EbuildPhase.py | 48 +++++++++----- pym/_emerge/EbuildProcess.py | 16 ++--- pym/_emerge/JobStatusDisplay.py | 8 +-- pym/_emerge/MiscFunctionsProcess.py | 10 +-- pym/_emerge/Scheduler.py | 21 +++--- pym/_emerge/SpawnProcess.py | 8 ++- pym/portage/__init__.py | 95 +++++++++++++++++++++------- pym/portage/dbapi/vartree.py | 12 ++++ pym/portage/update.py | 13 ++-- pym/portage/util.py | 8 +-- 19 files changed, 247 insertions(+), 97 deletions(-) create mode 100644 pym/_emerge/AbstractEbuildProcess.py diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 6062146a9..ee21fed5b 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -262,7 +262,19 @@ use_enable() { } register_die_hook() { - export EBUILD_DEATH_HOOKS="${EBUILD_DEATH_HOOKS} $*" + local x + for x in $* ; do + hasq $x $EBUILD_DEATH_HOOKS || \ + export EBUILD_DEATH_HOOKS="$EBUILD_DEATH_HOOKS $x" + done +} + +register_success_hook() { + local x + for x in $* ; do + hasq $x $EBUILD_SUCCESS_HOOKS || \ + export EBUILD_SUCCESS_HOOKS="$EBUILD_SUCCESS_HOOKS $x" + done } # Ensure that $PWD is sane whenever possible, to protect against @@ -739,7 +751,8 @@ dyn_clean() { if [[ $EMERGE_FROM = binary ]] || ! hasq keepwork $FEATURES; then rm -f "$PORTAGE_BUILDDIR"/.{ebuild_changed,exit_status,logid,unpacked,prepared} \ - "$PORTAGE_BUILDDIR"/.{configured,compiled,tested,packaged} + "$PORTAGE_BUILDDIR"/.{configured,compiled,tested,packaged} \ + "$PORTAGE_BUILDDIR"/.die_hooks rm -rf "${PORTAGE_BUILDDIR}/build-info" rm -rf "${WORKDIR}" diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh index 50c9800e2..012cd096e 100755 --- a/bin/isolated-functions.sh +++ b/bin/isolated-functions.sh @@ -156,6 +156,7 @@ die() { for x in $EBUILD_DEATH_HOOKS; do ${x} "$@" >&2 1>&2 done + > "$PORTAGE_BUILDDIR/.die_hooks" fi [[ -n ${PORTAGE_LOG_FILE} ]] \ diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh index f252c14be..c36e01f6d 100644 --- a/bin/misc-functions.sh +++ b/bin/misc-functions.sh @@ -1412,6 +1412,22 @@ dyn_rpm() { die "Failed to move rpm" } +die_hooks() { + [[ -f $PORTAGE_BUILDDIR/.die_hooks ]] && return + local x + for x in $EBUILD_DEATH_HOOKS ; do + $x >&2 + done + > "$PORTAGE_BUILDDIR/.die_hooks" +} + +success_hooks() { + local x + for x in $EBUILD_SUCCESS_HOOKS ; do + $x + done +} + if [ -n "${MISC_FUNCTIONS_ARGS}" ]; then source_all_bashrcs [ "$PORTAGE_DEBUG" == "1" ] && set -x diff --git a/bin/repoman b/bin/repoman index 0a858e907..d8f2ac8cd 100755 --- a/bin/repoman +++ b/bin/repoman @@ -409,7 +409,8 @@ live_eclasses = frozenset([ "darcs", "git", "mercurial", - "subversion" + "subversion", + "tla", ]) suspect_rdepend = frozenset([ diff --git a/cnf/sets.conf b/cnf/sets.conf index 311d4a38f..44ff8340c 100644 --- a/cnf/sets.conf +++ b/cnf/sets.conf @@ -57,7 +57,7 @@ world-candidate = False class = portage.sets.dbapi.VariableSet world-candidate = False variable = INHERITED -includes = bzr cvs darcs git mercurial subversion +includes = bzr cvs darcs git mercurial subversion tla # Installed packages that own files inside /lib/modules. [module-rebuild] diff --git a/man/ebuild.5 b/man/ebuild.5 index 67f7e3913..a81bcdcc3 100644 --- a/man/ebuild.5 +++ b/man/ebuild.5 @@ -719,6 +719,17 @@ VERINS="$(best_version net\-ftp/glftpd)" .br (VERINS now has the value "net\-ftp/glftpd\-1.27" if glftpd\-1.27 is installed) .RE +.SH "HELPER FUNCTIONS: HOOKS" +.TP +\fBregister_die_hook\fR \fI[list of function names]\fR +Register one or more functions to call when the ebuild fails for any reason, +including file collisions with other packages. +.TP +\fBregister_success_hook\fR \fI[list of function names]\fR +Register one or more functions to call when the ebuild builds and/or installs +successfully. +.TP +.RE .SH "HELPER FUNCTIONS: OUTPUT" .TP \fBeinfo\fR \fI"disposable message"\fR diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py new file mode 100644 index 000000000..db599019c --- /dev/null +++ b/pym/_emerge/AbstractEbuildProcess.py @@ -0,0 +1,24 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +from _emerge.SpawnProcess import SpawnProcess +import portage +from portage import os + +class AbstractEbuildProcess(SpawnProcess): + + __slots__ = ('phase', 'pkg', 'settings',) + + def _pipe(self, fd_pipes): + stdout_pipe = fd_pipes.get(1) + got_pty, master_fd, slave_fd = \ + portage._create_pty_or_pipe(copy_term_size=stdout_pipe) + return (master_fd, slave_fd) + + def _can_log(self, slave_fd): + # With sesandbox, logging works through a pty but not through a + # normal pipe. So, disable logging if ptys are broken. + # See Bug #162404. + return not ('sesandbox' in self.settings.features \ + and self.settings.selinux_enabled()) or os.isatty(slave_fd) diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py index 501c74fbe..add3a00b7 100644 --- a/pym/_emerge/EbuildBuild.py +++ b/pym/_emerge/EbuildBuild.py @@ -10,6 +10,7 @@ from _emerge.CompositeTask import CompositeTask from _emerge.EbuildMerge import EbuildMerge from _emerge.EbuildFetchonly import EbuildFetchonly from _emerge.EbuildBuildDir import EbuildBuildDir +from _emerge.MiscFunctionsProcess import MiscFunctionsProcess from portage.util import writemsg import portage from portage import os @@ -216,14 +217,13 @@ class EbuildBuild(CompositeTask): return if self.opts.buildpkgonly: - # Need to call "clean" phase for buildpkgonly mode - portage.elog.elog_process(self.pkg.cpv, self.settings) - phase = "clean" - clean_phase = EbuildPhase(background=self.background, - pkg=self.pkg, phase=phase, - scheduler=self.scheduler, settings=self.settings, - tree=self._tree) - self._start_task(clean_phase, self._clean_exit) + phase = 'success_hooks' + success_hooks = MiscFunctionsProcess( + background=self.background, + commands=[phase], phase=phase, pkg=self.pkg, + scheduler=self.scheduler, settings=self.settings) + self._start_task(success_hooks, + self._buildpkgonly_success_hook_exit) return # Continue holding the builddir lock until @@ -232,6 +232,18 @@ class EbuildBuild(CompositeTask): self.returncode = packager.returncode self.wait() + def _buildpkgonly_success_hook_exit(self, success_hooks): + self._default_exit(success_hooks) + self.returncode = None + # Need to call "clean" phase for buildpkgonly mode + portage.elog.elog_process(self.pkg.cpv, self.settings) + phase = 'clean' + clean_phase = EbuildPhase(background=self.background, + pkg=self.pkg, phase=phase, + scheduler=self.scheduler, settings=self.settings, + tree=self._tree) + self._start_task(clean_phase, self._clean_exit) + def _clean_exit(self, clean_phase): if self._final_exit(clean_phase) != os.EX_OK or \ self.opts.buildpkgonly: diff --git a/pym/_emerge/EbuildExecuter.py b/pym/_emerge/EbuildExecuter.py index 055a8fa47..adb7cd6e9 100644 --- a/pym/_emerge/EbuildExecuter.py +++ b/pym/_emerge/EbuildExecuter.py @@ -20,7 +20,8 @@ class EbuildExecuter(CompositeTask): "darcs", "git", "mercurial", - "subversion" + "subversion", + "tla", ]) def _start(self): diff --git a/pym/_emerge/EbuildPhase.py b/pym/_emerge/EbuildPhase.py index fcf60d39c..89bdb078f 100644 --- a/pym/_emerge/EbuildPhase.py +++ b/pym/_emerge/EbuildPhase.py @@ -5,10 +5,11 @@ from _emerge.MiscFunctionsProcess import MiscFunctionsProcess from _emerge.EbuildProcess import EbuildProcess from _emerge.CompositeTask import CompositeTask -from portage.util import writemsg +from portage.util import writemsg, writemsg_stdout import portage from portage import os from portage import _encodings +from portage import _unicode_decode from portage import _unicode_encode import codecs @@ -30,27 +31,28 @@ class EbuildPhase(CompositeTask): def _ebuild_exit(self, ebuild_process): if self.phase == "install": - out = None + out = portage.StringIO() log_path = self.settings.get("PORTAGE_LOG_FILE") log_file = None - if self.background and log_path is not None: + if log_path is not None: log_file = codecs.open(_unicode_encode(log_path, encoding=_encodings['fs'], errors='strict'), mode='a', encoding=_encodings['content'], errors='replace') - out = log_file try: portage._check_build_log(self.settings, out=out) + msg = _unicode_decode(out.getvalue(), + encoding=_encodings['content'], errors='replace') + if msg: + if not self.background: + writemsg_stdout(msg, noiselevel=-1) + if log_file is not None: + log_file.write(msg) finally: if log_file is not None: log_file.close() if self._default_exit(ebuild_process) != os.EX_OK: - if self.phase != 'clean' and \ - 'noclean' not in self.settings.features and \ - 'fail-clean' in self.settings.features: - self._fail_clean() - return - self.wait() + self._die_hooks() return settings = self.settings @@ -85,15 +87,31 @@ class EbuildPhase(CompositeTask): if self._final_exit(post_phase) != os.EX_OK: writemsg("!!! post %s failed; exiting.\n" % self.phase, noiselevel=-1) - if self.phase != 'clean' and \ - 'noclean' not in self.settings.features and \ - 'fail-clean' in self.settings.features: - self._fail_clean() - return + self._die_hooks() + return self._current_task = None self.wait() return + def _die_hooks(self): + self.returncode = None + phase = 'die_hooks' + die_hooks = MiscFunctionsProcess(background=self.background, + commands=[phase], phase=phase, pkg=self.pkg, + scheduler=self.scheduler, settings=self.settings) + self._start_task(die_hooks, self._die_hooks_exit) + + def _die_hooks_exit(self, die_hooks): + if self.phase != 'clean' and \ + 'noclean' not in self.settings.features and \ + 'fail-clean' in self.settings.features: + self._default_exit(die_hooks) + self._fail_clean() + return + self._final_exit(die_hooks) + self.returncode = 1 + self.wait() + def _fail_clean(self): self.returncode = None portage.elog.elog_process(self.pkg.cpv, self.settings) diff --git a/pym/_emerge/EbuildProcess.py b/pym/_emerge/EbuildProcess.py index 86a63282f..597caf4dd 100644 --- a/pym/_emerge/EbuildProcess.py +++ b/pym/_emerge/EbuildProcess.py @@ -2,13 +2,13 @@ # Distributed under the terms of the GNU General Public License v2 # $Id$ -from _emerge.SpawnProcess import SpawnProcess +from _emerge.AbstractEbuildProcess import AbstractEbuildProcess import portage from portage import os -class EbuildProcess(SpawnProcess): +class EbuildProcess(AbstractEbuildProcess): - __slots__ = ("phase", "pkg", "settings", "tree") + __slots__ = ('tree',) def _start(self): # Don't open the log file during the clean phase since the @@ -16,13 +16,7 @@ class EbuildProcess(SpawnProcess): # prevents the clean phase from removing $T. if self.phase not in ("clean", "cleanrm"): self.logfile = self.settings.get("PORTAGE_LOG_FILE") - SpawnProcess._start(self) - - def _pipe(self, fd_pipes): - stdout_pipe = fd_pipes.get(1) - got_pty, master_fd, slave_fd = \ - portage._create_pty_or_pipe(copy_term_size=stdout_pipe) - return (master_fd, slave_fd) + AbstractEbuildProcess._start(self) def _spawn(self, args, **kwargs): @@ -40,7 +34,7 @@ class EbuildProcess(SpawnProcess): return rval def _set_returncode(self, wait_retval): - SpawnProcess._set_returncode(self, wait_retval) + AbstractEbuildProcess._set_returncode(self, wait_retval) if self.phase not in ("clean", "cleanrm"): self.returncode = portage._doebuild_exit_status_check_and_log( diff --git a/pym/_emerge/JobStatusDisplay.py b/pym/_emerge/JobStatusDisplay.py index bcc682b23..288e355f6 100644 --- a/pym/_emerge/JobStatusDisplay.py +++ b/pym/_emerge/JobStatusDisplay.py @@ -5,15 +5,9 @@ import formatter import sys import time -try: - from io import StringIO -except ImportError: - # Needed for python-2.6 with USE=build since - # io imports threading which imports thread - # which is unavailable. - from StringIO import StringIO import portage +from portage import StringIO from portage import os from portage import _encodings from portage import _unicode_decode diff --git a/pym/_emerge/MiscFunctionsProcess.py b/pym/_emerge/MiscFunctionsProcess.py index 3e2fff7cc..63d7873ea 100644 --- a/pym/_emerge/MiscFunctionsProcess.py +++ b/pym/_emerge/MiscFunctionsProcess.py @@ -2,16 +2,16 @@ # Distributed under the terms of the GNU General Public License v2 # $Id$ -from _emerge.SpawnProcess import SpawnProcess +from _emerge.AbstractEbuildProcess import AbstractEbuildProcess import portage from portage import os -class MiscFunctionsProcess(SpawnProcess): +class MiscFunctionsProcess(AbstractEbuildProcess): """ Spawns misc-functions.sh with an existing ebuild environment. """ - __slots__ = ("commands", "phase", "pkg", "settings") + __slots__ = ('commands',) def _start(self): settings = self.settings @@ -26,7 +26,7 @@ class MiscFunctionsProcess(SpawnProcess): portage._doebuild_exit_status_unlink( settings.get("EBUILD_EXIT_STATUS_FILE")) - SpawnProcess._start(self) + AbstractEbuildProcess._start(self) def _spawn(self, args, **kwargs): settings = self.settings @@ -35,7 +35,7 @@ class MiscFunctionsProcess(SpawnProcess): debug=debug, **kwargs) def _set_returncode(self, wait_retval): - SpawnProcess._set_returncode(self, wait_retval) + AbstractEbuildProcess._set_returncode(self, wait_retval) self.returncode = portage._doebuild_exit_status_check_and_log( self.settings, self.phase, self.returncode) diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index dcd2e47c7..c760c395e 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -11,15 +11,8 @@ import textwrap import time import weakref -try: - from io import StringIO -except ImportError: - # Needed for python-2.6 with USE=build since - # io imports threading which imports thread - # which is unavailable. - from StringIO import StringIO - import portage +from portage import StringIO from portage import os from portage import _encodings from portage import _unicode_decode @@ -47,6 +40,7 @@ from _emerge._find_deep_system_runtime_deps import _find_deep_system_runtime_dep from _emerge._flush_elog_mod_echo import _flush_elog_mod_echo from _emerge.JobStatusDisplay import JobStatusDisplay from _emerge.MergeListItem import MergeListItem +from _emerge.MiscFunctionsProcess import MiscFunctionsProcess from _emerge.Package import Package from _emerge.PackageMerge import PackageMerge from _emerge.PollScheduler import PollScheduler @@ -550,9 +544,14 @@ class Scheduler(PollScheduler): background = self._background log_path = settings.get("PORTAGE_LOG_FILE") - ebuild_phase = EbuildPhase(background=background, - pkg=pkg, phase=phase, scheduler=scheduler, - settings=settings, tree=pkg_dblink.treetype) + if phase in ('die_hooks', 'success_hooks'): + ebuild_phase = MiscFunctionsProcess(background=background, + commands=[phase], phase=phase, pkg=pkg, + scheduler=scheduler, settings=settings) + else: + ebuild_phase = EbuildPhase(background=background, + pkg=pkg, phase=phase, scheduler=scheduler, + settings=settings, tree=pkg_dblink.treetype) ebuild_phase.start() ebuild_phase.wait() diff --git a/pym/_emerge/SpawnProcess.py b/pym/_emerge/SpawnProcess.py index 1486e6773..67fb17e29 100644 --- a/pym/_emerge/SpawnProcess.py +++ b/pym/_emerge/SpawnProcess.py @@ -49,7 +49,6 @@ class SpawnProcess(SubProcess): if fd == sys.stderr.fileno(): sys.stderr.flush() - logfile = self.logfile self._files = self._files_dict() files = self._files @@ -57,6 +56,10 @@ class SpawnProcess(SubProcess): fcntl.fcntl(master_fd, fcntl.F_SETFL, fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK) + logfile = None + if self._can_log(slave_fd): + logfile = self.logfile + null_input = None fd_pipes_orig = fd_pipes.copy() if self.background: @@ -125,6 +128,9 @@ class SpawnProcess(SubProcess): self.pid = retval[0] portage.process.spawned_pids.remove(self.pid) + def _can_log(self, slave_fd): + return True + def _pipe(self, fd_pipes): """ @type fd_pipes: dict diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 16202968b..e26b20521 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -33,6 +33,15 @@ try: from subprocess import getstatusoutput as subprocess_getstatusoutput except ImportError: from commands import getstatusoutput as subprocess_getstatusoutput + + try: + from io import StringIO + except ImportError: + # Needed for python-2.6 with USE=build since + # io imports threading which imports thread + # which is unavailable. + from StringIO import StringIO + from time import sleep from random import shuffle from itertools import chain @@ -2209,21 +2218,6 @@ class config(object): # initialize self.features self.regenerate() - if not portage.process.sandbox_capable and \ - ("sandbox" in self.features or "usersandbox" in self.features): - if self.profile_path is not None and \ - os.path.realpath(self.profile_path) == \ - os.path.realpath(os.path.join(config_root, PROFILE_PATH)): - """ Don't show this warning when running repoman and the - sandbox feature came from a profile that doesn't belong to - the user.""" - writemsg(colorize("BAD", _("!!! Problem with sandbox" - " binary. Disabling...\n\n")), noiselevel=-1) - if "sandbox" in self.features: - self.features.remove("sandbox") - if "usersandbox" in self.features: - self.features.remove("usersandbox") - if bsd_chflags: self.features.add('chflags') @@ -2360,6 +2354,18 @@ class config(object): writemsg("!!! /etc/portage/profile/virtuals. Please move it to\n") writemsg("!!! this new location.\n\n") + if not process.sandbox_capable and \ + ("sandbox" in self.features or "usersandbox" in self.features): + if self.profile_path is not None and \ + os.path.realpath(self.profile_path) == \ + os.path.realpath(os.path.join( + self["PORTAGE_CONFIGROOT"], PROFILE_PATH)): + # Don't show this warning when running repoman and the + # sandbox feature came from a profile that doesn't belong + # to the user. + writemsg(colorize("BAD", _("!!! Problem with sandbox" + " binary. Disabling...\n\n")), noiselevel=-1) + if "fakeroot" in self.features and \ not portage.process.fakeroot_capable: writemsg(_("!!! FEATURES=fakeroot is enabled, but the " @@ -4077,12 +4083,25 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero if 1 not in fd_pipes or 2 not in fd_pipes: raise ValueError(fd_pipes) + got_pty, master_fd, slave_fd = \ + _create_pty_or_pipe(copy_term_size=fd_pipes[1]) + + if not got_pty and 'sesandbox' in mysettings.features \ + and mysettings.selinux_enabled(): + # With sesandbox, logging works through a pty but not through a + # normal pipe. So, disable logging if ptys are broken. + # See Bug #162404. + logfile = None + os.close(master_fd) + master_fd = None + os.close(slave_fd) + slave_fd = None + + if logfile: + fd_pipes.setdefault(0, sys.stdin.fileno()) fd_pipes_orig = fd_pipes.copy() - got_pty, master_fd, slave_fd = \ - _create_pty_or_pipe(copy_term_size=fd_pipes_orig[1]) - # We must set non-blocking mode before we close the slave_fd # since otherwise the fcntl call can fail on FreeBSD (the child # process might have already exited and closed slave_fd so we @@ -4110,6 +4129,9 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero (not droppriv and "sandbox" not in features and \ "usersandbox" not in features and not fakeroot)) + if not free and not (fakeroot or process.sandbox_capable): + free = True + if free or "SANDBOX_ACTIVE" in os.environ: keywords["opt_name"] += " bash" spawn_func = portage.process.spawn_bash @@ -5649,7 +5671,23 @@ def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0, _post_phase_userpriv_perms(mysettings) if mydo == "install": - _check_build_log(mysettings) + out = StringIO() + _check_build_log(mysettings, out=out) + msg = _unicode_decode(out.getvalue(), + encoding=_encodings['content'], errors='replace') + if msg: + writemsg_stdout(msg, noiselevel=-1) + if logfile is not None: + try: + f = codecs.open(_unicode_encode(logfile, + encoding=_encodings['fs'], errors='strict'), + mode='a', encoding=_encodings['content'], + errors='replace') + except EnvironmentError: + pass + else: + f.write(msg) + f.close() if phase_retval == os.EX_OK: _post_src_install_chost_fix(mysettings) phase_retval = _post_src_install_checks(mysettings) @@ -5690,7 +5728,8 @@ def _post_phase_userpriv_perms(mysettings): def _post_src_install_checks(mysettings): _post_src_install_uid_fix(mysettings) global _post_phase_cmds - retval = _spawn_misc_sh(mysettings, _post_phase_cmds["install"]) + retval = _spawn_misc_sh(mysettings, _post_phase_cmds["install"], + phase='internal_post_src_install') if retval != os.EX_OK: writemsg(_("!!! install_qa_check failed; exiting.\n"), noiselevel=-1) @@ -5995,7 +6034,7 @@ def _post_pkg_postinst_cmd(mysettings): return myargs -def _spawn_misc_sh(mysettings, commands, **kwargs): +def _spawn_misc_sh(mysettings, commands, phase=None, **kwargs): """ @param mysettings: the ebuild config @type mysettings: config @@ -6015,14 +6054,14 @@ def _spawn_misc_sh(mysettings, commands, **kwargs): mysettings.get("EBUILD_EXIT_STATUS_FILE")) debug = mysettings.get("PORTAGE_DEBUG") == "1" logfile = mysettings.get("PORTAGE_LOG_FILE") - mydo = mysettings["EBUILD_PHASE"] + mysettings.pop("EBUILD_PHASE", None) try: rval = spawn(mycommand, mysettings, debug=debug, logfile=logfile, **kwargs) finally: pass - msg = _doebuild_exit_status_check(mydo, mysettings) + msg = _doebuild_exit_status_check(phase, mysettings) if msg: if rval == os.EX_OK: rval = 1 @@ -6346,6 +6385,13 @@ def prepare_build_dirs(myroot, mysettings, cleanup): writemsg(_("File Not Found: '%s'\n") % str(e), noiselevel=-1) return 1 + # Reset state for things like noauto and keepwork in FEATURES. + for x in ('.die_hooks',): + try: + os.unlink(os.path.join(mysettings['PORTAGE_BUILDDIR'], x)) + except OSError: + pass + _prepare_workdir(mysettings) if mysettings.get('EBUILD_PHASE') != 'fetch': # Avoid spurious permissions adjustments when fetching with @@ -7254,6 +7300,9 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, nosandbox = ("sandbox" not in features and \ "usersandbox" not in features) + if not process.sandbox_capable: + nosandbox = True + sesandbox = mysettings.selinux_enabled() and \ "sesandbox" in mysettings.features diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 9120a0cb6..c0c07c1c6 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -5405,6 +5405,18 @@ class dblink(object): retval = self.treewalk(mergeroot, myroot, inforoot, myebuild, cleanup=cleanup, mydbapi=mydbapi, prev_mtimes=prev_mtimes) + if retval == os.EX_OK: + phase = 'success_hooks' + else: + phase = 'die_hooks' + + if self._scheduler is None: + portage._spawn_misc_sh(self.settings, [phase], + phase=phase) + else: + self._scheduler.dblinkEbuildPhase( + self, mydbapi, myebuild, phase) + # Process ebuild logfiles elog_process(self.mycpv, self.settings, phasefilter=filter_mergephases) if 'noclean' not in self.settings.features and \ diff --git a/pym/portage/update.py b/pym/portage/update.py index 04812d5a4..af0fd2f42 100644 --- a/pym/portage/update.py +++ b/pym/portage/update.py @@ -201,15 +201,20 @@ def update_config_files(config_root, protect, protect_mask, update_iter): config_file = os.path.join(abs_user_config, x) if os.path.isdir(config_file): for parent, dirs, files in os.walk(config_file): - for y in dirs: + try: + parent = _unicode_decode(parent, + encoding=_encodings['fs'], errors='strict') + except UnicodeDecodeError: + continue + for y_enc in dirs: try: - y = _unicode_decode(y, + y = _unicode_decode(y_enc, encoding=_encodings['fs'], errors='strict') except UnicodeDecodeError: - dirs.remove(y) + dirs.remove(y_enc) continue if y.startswith("."): - dirs.remove(y) + dirs.remove(y_enc) for y in files: try: y = _unicode_decode(y, diff --git a/pym/portage/util.py b/pym/portage/util.py index 5a9376666..a507edbc8 100644 --- a/pym/portage/util.py +++ b/pym/portage/util.py @@ -24,15 +24,9 @@ import shlex import stat import string import sys -try: - from io import StringIO -except ImportError: - # Needed for python-2.6 with USE=build since - # io imports threading which imports thread - # which is unavailable. - from StringIO import StringIO import portage +from portage import StringIO from portage import os from portage import _encodings from portage import _os_merge -- 2.26.2