aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Sachau <tommy@gentoo.org>2016-02-28 13:32:23 +0100
committerThomas Sachau <tommy@gentoo.org>2016-02-28 13:32:23 +0100
commit2988e14465a24de9db00f5899239cb739e5de083 (patch)
treebb5db0815d5235384e89afbec1de521900557c9b
parentmerge v2.2.25 (diff)
parentUpdates for the 2.2.26 release (diff)
downloadportage-2988e144.tar.gz
portage-2988e144.tar.bz2
portage-2988e144.zip
merge v2.2.26
-rw-r--r--RELEASE-NOTES12
-rwxr-xr-xbin/egencache6
-rw-r--r--bin/phase-functions.sh13
-rw-r--r--bin/phase-helpers.sh17
-rw-r--r--pym/_emerge/SpawnProcess.py37
-rw-r--r--pym/_emerge/depgraph.py35
-rw-r--r--pym/portage/repository/config.py14
-rw-r--r--pym/portage/sync/controller.py7
-rw-r--r--pym/portage/sync/modules/cvs/__init__.py4
-rw-r--r--pym/portage/tests/resolver/test_autounmask_parent.py43
-rw-r--r--pym/portage/util/locale.py7
-rwxr-xr-xsetup.py2
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)
diff --git a/setup.py b/setup.py
index 0f08f5486..3c0ce0cc7 100755
--- a/setup.py
+++ b/setup.py
@@ -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',