diff options
author | Thomas Sachau <tommy@gentoo.org> | 2016-02-28 13:32:23 +0100 |
---|---|---|
committer | Thomas Sachau <tommy@gentoo.org> | 2016-02-28 13:32:23 +0100 |
commit | 2988e14465a24de9db00f5899239cb739e5de083 (patch) | |
tree | bb5db0815d5235384e89afbec1de521900557c9b | |
parent | merge v2.2.25 (diff) | |
parent | Updates for the 2.2.26 release (diff) | |
download | portage-2988e144.tar.gz portage-2988e144.tar.bz2 portage-2988e144.zip |
merge v2.2.26
-rw-r--r-- | RELEASE-NOTES | 12 | ||||
-rwxr-xr-x | bin/egencache | 6 | ||||
-rw-r--r-- | bin/phase-functions.sh | 13 | ||||
-rw-r--r-- | bin/phase-helpers.sh | 17 | ||||
-rw-r--r-- | pym/_emerge/SpawnProcess.py | 37 | ||||
-rw-r--r-- | pym/_emerge/depgraph.py | 35 | ||||
-rw-r--r-- | pym/portage/repository/config.py | 14 | ||||
-rw-r--r-- | pym/portage/sync/controller.py | 7 | ||||
-rw-r--r-- | pym/portage/sync/modules/cvs/__init__.py | 4 | ||||
-rw-r--r-- | pym/portage/tests/resolver/test_autounmask_parent.py | 43 | ||||
-rw-r--r-- | pym/portage/util/locale.py | 7 | ||||
-rwxr-xr-x | setup.py | 2 |
12 files changed, 164 insertions, 33 deletions
diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 69d96e87a..6a81495df 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -1,6 +1,18 @@ Release Notes; upgrade information mainly. Features/major bugfixes are listed in NEWS +portage-2.2.26 +================================== +* Bug Fixes: + - Bug 566372 enable absolute_import + fix python2.7 setlocale ValueError + - Bug 566414 SpawnProcess: make _cancel kill all processes in cgroup + - Bug 566420 SpawnProcess: re-check cgroup.procs until empty + - Bug 566654 einstalldocs: use lazy docinto calls (prevent empty dir) + - Bug 566132 SyncManager: redirect command stderr to stdout + - Bug 566704 depgraph: autounmask for conditional USE deps +* other EAPI 6 code changes: eapply_user, several corrections + portage-2.2.25 ================================== * Bug Fixes: diff --git a/bin/egencache b/bin/egencache index 1cc2f3d4f..ab36bbea7 100755 --- a/bin/egencache +++ b/bin/egencache @@ -75,8 +75,6 @@ else: else: from repoman.metadata import parse_metadata_use -from repoman.vcs.vcs import FindVCS - if sys.hexversion >= 0x3000000: # pylint: disable=W0622 long = int @@ -920,9 +918,7 @@ class GenChangeLogs(object): output.close() def _task_iter(self): - os.chdir(self._repo_path) - - if 'git' not in FindVCS(): + if not os.path.isdir(os.environ.get('GIT_DIR', os.path.join(self._repo_path, '.git'))): writemsg_level( "ERROR: --update-changelogs supported only in git repos\n", level=logging.ERROR, noiselevel=-1) diff --git a/bin/phase-functions.sh b/bin/phase-functions.sh index 6f98569b1..96ed3391e 100644 --- a/bin/phase-functions.sh +++ b/bin/phase-functions.sh @@ -222,6 +222,12 @@ __dyn_pretend() { } __dyn_setup() { + if [[ -e $PORTAGE_BUILDDIR/.setuped ]] ; then + __vecho ">>> It appears that '$PF' is already setup; skipping." + __vecho ">>> Remove '$PORTAGE_BUILDDIR/.setuped' to force setup." + return + fi + if [[ " ${FEATURES} " == *" force-multilib "* ]]; then if ! is_auto-multilib && ! use multilib_abi_"${DEFAULT_ABI}" ; then ewarn @@ -270,7 +276,7 @@ __dyn_unpack() { >> "$PORTAGE_BUILDDIR/.unpacked" || \ die "Failed to create $PORTAGE_BUILDDIR/.unpacked" __vecho ">>> Source unpacked in ${WORKDIR}" - __ebuild_phase post_src_unpack +__ebuild_phase post_src_unpack } __dyn_clean() { @@ -411,6 +417,11 @@ __dyn_prepare() { done + # keep path in eapply_user in sync! + if ___eapi_has_eapply_user && [[ ! -f ${T}/.portage_user_patches_applied ]]; then + die "eapply_user (or default) must be called in src_prepare()!" + fi + >> "$PORTAGE_BUILDDIR/.prepared" || \ die "Failed to create $PORTAGE_BUILDDIR/.prepared" __vecho ">>> Source prepared." diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh index 880460eae..4a0c638ca 100644 --- a/bin/phase-helpers.sh +++ b/bin/phase-helpers.sh @@ -955,26 +955,26 @@ fi if ___eapi_has_einstalldocs; then einstalldocs() { ( - docinto . if ! declare -p DOCS &>/dev/null ; then local d for d in README* ChangeLog AUTHORS NEWS TODO CHANGES \ THANKS BUGS FAQ CREDITS CHANGELOG ; do - [[ -s ${d} ]] && dodoc "${d}" + [[ -s ${d} ]] && docinto / && dodoc "${d}" done elif [[ $(declare -p DOCS) == "declare -a"* ]] ; then - [[ ${DOCS[@]} ]] && dodoc -r "${DOCS[@]}" + [[ ${DOCS[@]} ]] && docinto / && dodoc -r "${DOCS[@]}" else - [[ ${DOCS} ]] && dodoc -r ${DOCS} + [[ ${DOCS} ]] && docinto / && dodoc -r ${DOCS} fi ) ( - docinto html if [[ $(declare -p HTML_DOCS 2>/dev/null) == "declare -a"* ]] ; then - [[ ${HTML_DOCS[@]} ]] && dodoc -r "${HTML_DOCS[@]}" + [[ ${HTML_DOCS[@]} ]] && \ + docinto html && dodoc -r "${HTML_DOCS[@]}" else - [[ ${HTML_DOCS} ]] && dodoc -r ${HTML_DOCS} + [[ ${HTML_DOCS} ]] && \ + docinto html && dodoc -r ${HTML_DOCS} fi ) } @@ -1080,6 +1080,9 @@ fi if ___eapi_has_eapply_user; then eapply_user() { + [[ ${EBUILD_PHASE} == prepare ]] || \ + die "eapply_user() called during invalid phase: ${EBUILD_PHASE}" + # keep path in __dyn_prepare in sync! local tagfile=${T}/.portage_user_patches_applied [[ -f ${tagfile} ]] && return >> "${tagfile}" diff --git a/pym/_emerge/SpawnProcess.py b/pym/_emerge/SpawnProcess.py index 5ab2e67d1..e046640ea 100644 --- a/pym/_emerge/SpawnProcess.py +++ b/pym/_emerge/SpawnProcess.py @@ -16,6 +16,8 @@ from _emerge.SubProcess import SubProcess import portage from portage import os from portage.const import BASH_BINARY +from portage.localization import _ +from portage.output import EOutput from portage.util import writemsg_level from portage.util._async.PipeLogger import PipeLogger @@ -35,6 +37,10 @@ class SpawnProcess(SubProcess): __slots__ = ("args",) + \ _spawn_kwarg_names + ("_pipe_logger", "_selinux_type",) + # Max number of attempts to kill the processes listed in cgroup.procs, + # given that processes may fork before they can be killed. + _CGROUP_CLEANUP_RETRY_MAX = 8 + def _start(self): if self.fd_pipes is None: @@ -179,7 +185,13 @@ class SpawnProcess(SubProcess): def _set_returncode(self, wait_retval): SubProcess._set_returncode(self, wait_retval) + self._cgroup_cleanup() + + def _cancel(self): + SubProcess._cancel(self) + self._cgroup_cleanup() + def _cgroup_cleanup(self): if self.cgroup: def get_pids(cgroup): try: @@ -203,10 +215,24 @@ class SpawnProcess(SubProcess): elif e.errno != errno.ESRCH: raise - # step 1: kill all orphans - pids = get_pids(self.cgroup) + # step 1: kill all orphans (loop in case of new forks) + remaining = self._CGROUP_CLEANUP_RETRY_MAX + while remaining: + remaining -= 1 + pids = get_pids(self.cgroup) + if pids: + kill_all(pids, signal.SIGKILL) + else: + break + if pids: - kill_all(pids, signal.SIGKILL) + msg = [] + msg.append( + _("Failed to kill pid(s) in '%(cgroup)s': %(pids)s") % dict( + cgroup=os.path.join(self.cgroup, 'cgroup.procs'), + pids=' '.join(str(pid) for pid in pids))) + + self._elog('eerror', msg) # step 2: remove the cgroup try: @@ -215,3 +241,8 @@ class SpawnProcess(SubProcess): # it may be removed already, or busy # we can't do anything good about it pass + + def _elog(self, elog_funcname, lines): + elog_func = getattr(EOutput(), elog_funcname) + for line in lines: + elog_func(line) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 57040abce..f659b0a16 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -4075,6 +4075,7 @@ class depgraph(object): # Now that the root packages have been added to the graph, # process the dependencies. if not self._create_graph(): + self._apply_parent_use_changes() return 0, myfavorites try: @@ -4162,6 +4163,24 @@ class depgraph(object): # We're true here unless we are missing binaries. return (True, myfavorites) + def _apply_parent_use_changes(self): + """ + For parents with unsatisfied conditional dependencies, translate + USE change suggestions into autounmask changes. + """ + if (self._dynamic_config._unsatisfied_deps_for_display and + self._dynamic_config._autounmask): + remaining_items = [] + for item in self._dynamic_config._unsatisfied_deps_for_display: + pargs, kwargs = item + kwargs = kwargs.copy() + kwargs['collect_use_changes'] = True + if not self._show_unsatisfied_dep(*pargs, + **portage._native_kwargs(kwargs)): + remaining_items.append(item) + if len(remaining_items) != len(self._dynamic_config._unsatisfied_deps_for_display): + self._dynamic_config._unsatisfied_deps_for_display = remaining_items + def _set_args(self, args): """ Create the "__non_set_args__" package set from atoms and packages given as @@ -4718,7 +4737,8 @@ class depgraph(object): def _show_unsatisfied_dep(self, root, atom, myparent=None, arg=None, - check_backtrack=False, check_autounmask_breakage=False, show_req_use=None): + check_backtrack=False, check_autounmask_breakage=False, show_req_use=None, + collect_use_changes=False): """ When check_backtrack=True, no output is produced and the method either returns or raises _backtrack_mask if @@ -4962,15 +4982,28 @@ class depgraph(object): "defined by %s: '%s'" % (myparent.cpv, \ human_readable_required_use(required_use)) + target_use = {} for flag in involved_flags: if flag in self._pkg_use_enabled(myparent): + target_use[flag] = False changes.append(colorize("blue", "-" + flag)) else: + target_use[flag] = True changes.append(colorize("red", "+" + flag)) + + if collect_use_changes and not required_use_warning: + previous_changes = self._dynamic_config._needed_use_config_changes.get(myparent) + self._pkg_use_enabled(myparent, target_use=target_use) + if previous_changes is not self._dynamic_config._needed_use_config_changes.get(myparent): + return True + mreasons.append("Change USE: %s" % " ".join(changes) + required_use_warning) if (myparent, mreasons) not in missing_use_reasons: missing_use_reasons.append((myparent, mreasons)) + if collect_use_changes: + return False + unmasked_use_reasons = [(pkg, mreasons) for (pkg, mreasons) \ in missing_use_reasons if pkg not in masked_pkg_instances] diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py index ffb454445..a21c8910c 100644 --- a/pym/portage/repository/config.py +++ b/pym/portage/repository/config.py @@ -454,7 +454,7 @@ class RepoConfigLoader(object): @staticmethod def _add_repositories(portdir, portdir_overlay, prepos, - ignored_map, ignored_location_map, local_config, default_portdir): + ignored_map, local_config, default_portdir): """Add overlays in PORTDIR_OVERLAY as repositories""" overlays = [] portdir_orig = None @@ -524,7 +524,6 @@ class RepoConfigLoader(object): not (base_priority == 0 and old_location == default_portdir): ignored_map.setdefault(repo.name, []).append(old_location) - ignored_location_map[old_location] = repo.name if old_location == portdir: portdir = repo.user_location @@ -547,7 +546,7 @@ class RepoConfigLoader(object): return portdir @staticmethod - def _parse(paths, prepos, ignored_map, ignored_location_map, local_config, portdir, default_opts): + def _parse(paths, prepos, local_config, default_opts): """Parse files in paths to load config""" parser = SafeConfigParser(defaults=default_opts) @@ -621,7 +620,6 @@ class RepoConfigLoader(object): location_map = {} treemap = {} ignored_map = {} - ignored_location_map = {} default_opts = { "EPREFIX" : settings["EPREFIX"], "EROOT" : settings["EROOT"], @@ -644,9 +642,7 @@ class RepoConfigLoader(object): settings.get("PORTAGE_RSYNC_EXTRA_OPTS", None) try: - self._parse(paths, prepos, ignored_map, - ignored_location_map, settings.local_config, - portdir, default_opts) + self._parse(paths, prepos, settings.local_config, default_opts) except ConfigParserError as e: writemsg( _("!!! Error while reading repo config file: %s\n") % e, @@ -659,8 +655,6 @@ class RepoConfigLoader(object): {}, local_config=settings.local_config) location_map.clear() treemap.clear() - ignored_map.clear() - ignored_location_map.clear() default_portdir = os.path.join(os.sep, settings['EPREFIX'].lstrip(os.sep), 'usr', 'portage') @@ -668,7 +662,7 @@ class RepoConfigLoader(object): # If PORTDIR_OVERLAY contains a repo with the same repo_name as # PORTDIR, then PORTDIR is overridden. portdir = self._add_repositories(portdir, portdir_overlay, prepos, - ignored_map, ignored_location_map, settings.local_config, + ignored_map, settings.local_config, default_portdir) if portdir and portdir.strip(): portdir = os.path.realpath(portdir) diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py index 4595293c6..e71ba67a5 100644 --- a/pym/portage/sync/controller.py +++ b/pym/portage/sync/controller.py @@ -218,6 +218,13 @@ class SyncManager(object): self.usersync_uid = None spawn_kwargs = {} + # Redirect command stderr to stdout, in order to prevent + # spurious cron job emails (bug 566132). + spawn_kwargs["fd_pipes"] = { + 0: sys.__stdin__.fileno(), + 1: sys.__stdout__.fileno(), + 2: sys.__stdout__.fileno() + } spawn_kwargs["env"] = self.settings.environ() if repo.sync_user is not None: def get_sync_user_data(sync_user): diff --git a/pym/portage/sync/modules/cvs/__init__.py b/pym/portage/sync/modules/cvs/__init__.py index 952053ad5..0cf60673c 100644 --- a/pym/portage/sync/modules/cvs/__init__.py +++ b/pym/portage/sync/modules/cvs/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014 Gentoo Foundation +# Copyright 2014-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 doc = """CVS plug-in module for portage. @@ -18,7 +18,7 @@ class CheckCVSConfig(CheckSyncConfig): def check_cvs_repo(self): - if self.repo.module_specific_options['sync-cvs-repo'] is None: + if self.repo.module_specific_options.get('sync-cvs-repo') is None: writemsg_level("!!! %s\n" % _("Repository '%s' has sync-type=cvs, but is missing sync-cvs-repo attribute") % self.repo.name, level=self.logger.ERROR, noiselevel=-1) diff --git a/pym/portage/tests/resolver/test_autounmask_parent.py b/pym/portage/tests/resolver/test_autounmask_parent.py new file mode 100644 index 000000000..042acabb0 --- /dev/null +++ b/pym/portage/tests/resolver/test_autounmask_parent.py @@ -0,0 +1,43 @@ +# Copyright 2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ( + ResolverPlayground, + ResolverPlaygroundTestCase, +) + +class AutounmaskParentTestCase(TestCase): + + def testAutounmaskParentUse(self): + + ebuilds = { + "dev-libs/B-1": { + "EAPI": "5", + "DEPEND": "dev-libs/D[foo(-)?,bar(-)?]", + "IUSE": "+bar +foo", + }, + "dev-libs/D-1": {}, + } + + test_cases = ( + # Test bug 566704 + ResolverPlaygroundTestCase( + ["=dev-libs/B-1"], + options={"--autounmask": True}, + success=False, + use_changes={ + "dev-libs/B-1": { + "foo": False, + "bar": False, + } + }), + ) + + playground = ResolverPlayground(ebuilds=ebuilds) + try: + for test_case in test_cases: + playground.run_TestCase(test_case) + self.assertEqual(test_case.test_success, True, test_case.fail_msg) + finally: + playground.cleanup() diff --git a/pym/portage/util/locale.py b/pym/portage/util/locale.py index c3332ea54..2a15ea1b1 100644 --- a/pym/portage/util/locale.py +++ b/pym/portage/util/locale.py @@ -6,7 +6,7 @@ Function to check whether the current used LC_CTYPE handles case transformations of ASCII characters in a way compatible with the POSIX locale. """ -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals import locale import logging @@ -14,6 +14,7 @@ import os import textwrap import traceback +import portage from portage.util import writemsg_level from portage.util._ctypes import find_library, LoadLibrary @@ -26,7 +27,6 @@ locale_categories = ( 'LC_PAPER', 'LC_TELEPHONE', ) - _check_locale_cache = {} @@ -103,7 +103,8 @@ def check_locale(silent=False, env=None): try: if env is not None: try: - locale.setlocale(locale.LC_CTYPE, mylocale) + locale.setlocale(locale.LC_CTYPE, + portage._native_string(mylocale)) except locale.Error: os._exit(2) @@ -615,7 +615,7 @@ def get_manpages(): setup( name = 'portage', - version = '2.2.25', + version = '2.2.26', url = 'https://wiki.gentoo.org/wiki/Project:Portage', author = 'Gentoo Portage Development Team', author_email = 'dev-portage@gentoo.org', |