aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2017-03-08 14:25:56 -0800
committerZac Medico <zmedico@gentoo.org>2017-03-09 11:33:54 -0800
commitc01f3fbd23def329eb1d1b0fc8f79959119a8a82 (patch)
tree09a4cf40ba11fcab505f2db57e6d2b8165a7eef4
parentdepgraph: fix backtracking for slot operator rebuilds (bug 612042) (diff)
downloadportage-c01f3fbd.tar.gz
portage-c01f3fbd.tar.bz2
portage-c01f3fbd.zip
depgraph: fix runtime package mask interaction with slot operator rebuilds (bug 612094)
In some cases the backtracking runtime package mask can interact badly with slot operator rebuilds, preventing a solution from being found. This patch fixes the problem, which is demonstrated by the included unit test. X-Gentoo-bug: 612094 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612094 Acked-by: Brian Dolbec <dolsen@gentoo.org>
-rw-r--r--pym/_emerge/depgraph.py28
-rw-r--r--pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py136
2 files changed, 152 insertions, 12 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index bb3e307f0..1379b0563 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -1597,9 +1597,6 @@ class depgraph(object):
atom.package and atom.slot_operator_built):
continue
- if pkg not in conflict_pkgs:
- continue
-
for other_pkg in slot_nodes:
if other_pkg in conflict_pkgs:
continue
@@ -2569,18 +2566,25 @@ class depgraph(object):
# runtime_pkg_mask, since that would trigger an
# infinite backtracking loop.
if self._dynamic_config._allow_backtracking:
- if dep.parent in self._dynamic_config._runtime_pkg_mask:
- if debug:
- writemsg(
- "!!! backtracking loop detected: %s %s\n" % \
- (dep.parent,
- self._dynamic_config._runtime_pkg_mask[
- dep.parent]), noiselevel=-1)
- elif dep.atom.package and dep.atom.slot_operator_built and \
- self._slot_operator_unsatisfied_probe(dep):
+ if (dep.parent not in self._dynamic_config._runtime_pkg_mask and
+ dep.atom.package and dep.atom.slot_operator_built and
+ self._slot_operator_unsatisfied_probe(dep)):
self._slot_operator_unsatisfied_backtrack(dep)
return 1
else:
+ # This is for backward-compatibility with previous
+ # behavior, so that installed packages with unsatisfied
+ # dependencies trigger an error message but do not
+ # cause the dependency calculation to fail. Only do
+ # this if the parent is already in the runtime package
+ # mask, since otherwise we need to backtrack.
+ if (dep.parent.installed and
+ dep.parent in self._dynamic_config._runtime_pkg_mask and
+ not any(self._iter_match_pkgs_any(
+ dep.parent.root_config, dep.atom))):
+ self._dynamic_config._initially_unsatisfied_deps.append(dep)
+ return 1
+
# Do not backtrack if only USE have to be changed in
# order to satisfy the dependency. Note that when
# want_restart_for_use_change sets the need_restart
diff --git a/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py b/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py
new file mode 100644
index 000000000..0a5a7fa78
--- /dev/null
+++ b/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py
@@ -0,0 +1,136 @@
+# Copyright 2017 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 SlotOperatorRuntimePkgMaskTestCase(TestCase):
+
+ def testSlotOperatorRuntimePkgMask(self):
+
+ ebuilds = {
+ "app-misc/meta-pkg-2" : {
+ "EAPI": "6",
+ "DEPEND": "=app-misc/B-2 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-2",
+ "RDEPEND": "=app-misc/B-2 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-2",
+ },
+
+ "app-misc/meta-pkg-1" : {
+ "EAPI": "6",
+ "DEPEND": "=app-misc/B-1 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-1",
+ "RDEPEND": "=app-misc/B-1 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-1",
+ },
+
+ "app-misc/B-1" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:=",
+ "RDEPEND": "dev-libs/foo:=",
+ },
+
+ "app-misc/B-2" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:=",
+ "RDEPEND": "dev-libs/foo:=",
+ },
+
+ "app-misc/C-1" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:=",
+ "RDEPEND": "dev-libs/foo:=",
+ },
+
+ "app-misc/C-2" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:=",
+ "RDEPEND": "dev-libs/foo:=",
+ },
+
+ "app-misc/D-1" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:=",
+ "RDEPEND": "dev-libs/foo:=",
+ },
+
+ "app-misc/D-2" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:=",
+ "RDEPEND": "dev-libs/foo:=",
+ },
+
+ "dev-libs/foo-1" : {
+ "EAPI": "6",
+ "SLOT": "0/1",
+ },
+
+ "dev-libs/foo-2" : {
+ "EAPI": "6",
+ "SLOT": "0/2",
+ },
+ }
+
+ installed = {
+ "app-misc/meta-pkg-1" : {
+ "EAPI": "6",
+ "DEPEND": "=app-misc/B-1 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-1",
+ "RDEPEND": "=app-misc/B-1 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-1",
+ },
+
+ "app-misc/B-1" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:0/1=",
+ "RDEPEND": "dev-libs/foo:0/1=",
+ },
+
+ "app-misc/C-1" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:0/1=",
+ "RDEPEND": "dev-libs/foo:0/1=",
+ },
+
+ "app-misc/D-1" : {
+ "EAPI": "6",
+ "DEPEND": "dev-libs/foo:0/1=",
+ "RDEPEND": "dev-libs/foo:0/1=",
+ },
+
+ "dev-libs/foo-1" : {
+ "EAPI": "6",
+ "SLOT": "0/1",
+ },
+ }
+
+ world = (
+ "app-misc/meta-pkg",
+ )
+
+ test_cases = (
+ ResolverPlaygroundTestCase(
+ ["=app-misc/meta-pkg-2"],
+ options = {
+ "--backtrack": 5,
+ },
+ success = True,
+ ambiguous_merge_order = True,
+ mergelist = [
+ 'dev-libs/foo-2',
+ ('app-misc/D-1', 'app-misc/C-1', 'app-misc/B-2'),
+ 'app-misc/meta-pkg-2',
+ ]
+ ),
+ )
+
+ playground = ResolverPlayground(debug=False,
+ ebuilds=ebuilds, installed=installed,
+ world=world)
+ try:
+ for test_case in test_cases:
+ playground.run_TestCase(test_case)
+ self.assertEqual(test_case.test_success, True,
+ test_case.fail_msg)
+ finally:
+ # Disable debug so that cleanup works.
+ playground.debug = False
+ playground.cleanup()