[prev in list] [next in list] [prev in thread] [next in thread]
List: gentoo-portage-dev
Subject: [gentoo-portage-dev] [PATCH] _solve_non_slot_operator_slot_conflicts: fix bug #510270
From: Zac Medico <zmedico () gentoo ! org>
Date: 2014-09-16 18:37:34
Message-ID: 5418836E.2040705 () gentoo ! org
[Download RAW message or body]
This fixes an IndexError in _solve_non_slot_operator_slot_conflicts
which occurs when none of the conflict packages matched a particular
atom. This typically means that autounmask broke a USE-dep, but it could
also be due to the slot not matching due to multislot (bug #220341).
Either way, don't try to solve this conflict. Instead, force all of the
associated conflict nodes into the graph so that they are protected from
removal by the conflict solver.
X-Gentoo-Bug: 510270
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=510270
---
pym/_emerge/depgraph.py | 14 +++++
pym/portage/tests/resolver/ResolverPlayground.py | 9 ++++
.../tests/resolver/test_autounmask_use_breakage.py | 63 ++++++++++++++++++++++
3 files changed, 86 insertions(+)
create mode 100644 pym/portage/tests/resolver/test_autounmask_use_breakage.py
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index cc87d9f..b31f90c 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -1059,6 +1059,7 @@ class depgraph(object):
def __str__(self):
return "(%s)" % ",".join(str(pkg) for pkg in self)
+ non_matching_forced = set()
for conflict in conflicts:
if debug:
writemsg_level(" conflict:\n", level=logging.DEBUG, noiselevel=-1)
@@ -1105,6 +1106,18 @@ class depgraph(object):
continue
elif len(matched) == 1:
conflict_graph.add(matched[0], parent)
+ elif len(matched) == 0:
+ # This typically means that autounmask broke a
+ # USE-dep, but it could also be due to the slot
+ # not matching due to multislot (bug #220341).
+ # Either way, don't try to solve this conflict.
+ # Instead, force them all into the graph so that
+ # they are protected from removal.
+ non_matching_forced.update(conflict)
+ if debug:
+ for pkg in conflict:
+ writemsg_level(" non-match: %s\n" % pkg,
+ level=logging.DEBUG, noiselevel=-1)
else:
# More than one packages matched, but not all.
conflict_graph.add(or_tuple(matched), parent)
@@ -1125,6 +1138,7 @@ class depgraph(object):
# Now select required packages. Collect them in the
# 'forced' set.
forced = set([non_conflict_node])
+ forced.update(non_matching_forced)
unexplored = set([non_conflict_node])
# or_tuples get special handling. We first explore
# all packages in the hope of having forced one of
diff --git a/pym/portage/tests/resolver/ResolverPlayground.py \
b/pym/portage/tests/resolver/ResolverPlayground.py index 77a5b5c..b1974d7 100644
--- a/pym/portage/tests/resolver/ResolverPlayground.py
+++ b/pym/portage/tests/resolver/ResolverPlayground.py
@@ -549,6 +549,7 @@ class ResolverPlaygroundTestCase(object):
self.all_permutations = kwargs.pop("all_permutations", False)
self.ignore_mergelist_order = kwargs.pop("ignore_mergelist_order", False)
self.ambiguous_merge_order = kwargs.pop("ambiguous_merge_order", False)
+ self.ambiguous_slot_collision_solutions = \
kwargs.pop("ambiguous_slot_collision_solutions", False) self.check_repo_names = \
kwargs.pop("check_repo_names", False) self.merge_order_assertions = \
kwargs.pop("merge_order_assertions", False)
@@ -664,6 +665,14 @@ class ResolverPlaygroundTestCase(object):
str((node1, node2))) + \
", got: " + str(got))
+ elif key == "slot_collision_solutions" and \
+ self.ambiguous_slot_collision_solutions:
+ # Tests that use all_permutations can have multiple
+ # outcomes here.
+ for x in expected:
+ if x == got:
+ expected = x
+ break
elif key in ("unstable_keywords", "needed_p_mask_changes",
"unsatisfied_deps") and expected is not None:
expected = set(expected)
diff --git a/pym/portage/tests/resolver/test_autounmask_use_breakage.py \
b/pym/portage/tests/resolver/test_autounmask_use_breakage.py new file mode 100644
index 0000000..3654aa6
--- /dev/null
+++ b/pym/portage/tests/resolver/test_autounmask_use_breakage.py
@@ -0,0 +1,63 @@
+# Copyright 2014 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 AutounmaskUseBreakageTestCase(TestCase):
+
+ def testAutounmaskUseBreakage(self):
+
+ ebuilds = {
+
+ "app-misc/A-0" : {
+ "EAPI": "5",
+ "RDEPEND": "app-misc/D[-foo]",
+ },
+
+ "app-misc/B-0" : {
+ "EAPI": "5",
+ "RDEPEND": "app-misc/D[foo]"
+ },
+
+ "app-misc/C-0" : {
+ "EAPI": "5",
+ "RDEPEND": ">=app-misc/D-1"
+ },
+
+ "app-misc/D-0" : {
+ "EAPI": "5",
+ "IUSE": "foo"
+ },
+
+ "app-misc/D-1" : {
+ "EAPI": "5",
+ "IUSE": "bar"
+ },
+
+ }
+
+ test_cases = (
+
+ # Bug 510270
+ # _solve_non_slot_operator_slot_conflicts throws
+ # IndexError: tuple index out of range
+ # due to autounmask USE breakage.
+ ResolverPlaygroundTestCase(
+ ["app-misc/C", "app-misc/B", "app-misc/A"],
+ all_permutations = True,
+ success = False,
+ ambiguous_slot_collision_solutions = True,
+ slot_collision_solutions = [None, []]
+ ),
+
+ )
+
+ playground = ResolverPlayground(ebuilds=ebuilds, debug=False)
+ 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()
--
1.8.5.5
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic