1 |
This fixes an IndexError in _solve_non_slot_operator_slot_conflicts |
2 |
which occurs when none of the conflict packages matched a particular |
3 |
atom. This typically means that autounmask broke a USE-dep, but it could |
4 |
also be due to the slot not matching due to multislot (bug #220341). |
5 |
Either way, don't try to solve this conflict. Instead, force all of the |
6 |
associated conflict nodes into the graph so that they are protected from |
7 |
removal by the conflict solver. |
8 |
|
9 |
X-Gentoo-Bug: 510270 |
10 |
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=510270 |
11 |
--- |
12 |
pym/_emerge/depgraph.py | 14 +++++ |
13 |
pym/portage/tests/resolver/ResolverPlayground.py | 9 ++++ |
14 |
.../tests/resolver/test_autounmask_use_breakage.py | 63 ++++++++++++++++++++++ |
15 |
3 files changed, 86 insertions(+) |
16 |
create mode 100644 pym/portage/tests/resolver/test_autounmask_use_breakage.py |
17 |
|
18 |
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py |
19 |
index cc87d9f..b31f90c 100644 |
20 |
--- a/pym/_emerge/depgraph.py |
21 |
+++ b/pym/_emerge/depgraph.py |
22 |
@@ -1059,6 +1059,7 @@ class depgraph(object): |
23 |
def __str__(self): |
24 |
return "(%s)" % ",".join(str(pkg) for pkg in self) |
25 |
|
26 |
+ non_matching_forced = set() |
27 |
for conflict in conflicts: |
28 |
if debug: |
29 |
writemsg_level(" conflict:\n", level=logging.DEBUG, noiselevel=-1) |
30 |
@@ -1105,6 +1106,18 @@ class depgraph(object): |
31 |
continue |
32 |
elif len(matched) == 1: |
33 |
conflict_graph.add(matched[0], parent) |
34 |
+ elif len(matched) == 0: |
35 |
+ # This typically means that autounmask broke a |
36 |
+ # USE-dep, but it could also be due to the slot |
37 |
+ # not matching due to multislot (bug #220341). |
38 |
+ # Either way, don't try to solve this conflict. |
39 |
+ # Instead, force them all into the graph so that |
40 |
+ # they are protected from removal. |
41 |
+ non_matching_forced.update(conflict) |
42 |
+ if debug: |
43 |
+ for pkg in conflict: |
44 |
+ writemsg_level(" non-match: %s\n" % pkg, |
45 |
+ level=logging.DEBUG, noiselevel=-1) |
46 |
else: |
47 |
# More than one packages matched, but not all. |
48 |
conflict_graph.add(or_tuple(matched), parent) |
49 |
@@ -1125,6 +1138,7 @@ class depgraph(object): |
50 |
# Now select required packages. Collect them in the |
51 |
# 'forced' set. |
52 |
forced = set([non_conflict_node]) |
53 |
+ forced.update(non_matching_forced) |
54 |
unexplored = set([non_conflict_node]) |
55 |
# or_tuples get special handling. We first explore |
56 |
# all packages in the hope of having forced one of |
57 |
diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py |
58 |
index 77a5b5c..b1974d7 100644 |
59 |
--- a/pym/portage/tests/resolver/ResolverPlayground.py |
60 |
+++ b/pym/portage/tests/resolver/ResolverPlayground.py |
61 |
@@ -549,6 +549,7 @@ class ResolverPlaygroundTestCase(object): |
62 |
self.all_permutations = kwargs.pop("all_permutations", False) |
63 |
self.ignore_mergelist_order = kwargs.pop("ignore_mergelist_order", False) |
64 |
self.ambiguous_merge_order = kwargs.pop("ambiguous_merge_order", False) |
65 |
+ self.ambiguous_slot_collision_solutions = kwargs.pop("ambiguous_slot_collision_solutions", False) |
66 |
self.check_repo_names = kwargs.pop("check_repo_names", False) |
67 |
self.merge_order_assertions = kwargs.pop("merge_order_assertions", False) |
68 |
|
69 |
@@ -664,6 +665,14 @@ class ResolverPlaygroundTestCase(object): |
70 |
str((node1, node2))) + \ |
71 |
", got: " + str(got)) |
72 |
|
73 |
+ elif key == "slot_collision_solutions" and \ |
74 |
+ self.ambiguous_slot_collision_solutions: |
75 |
+ # Tests that use all_permutations can have multiple |
76 |
+ # outcomes here. |
77 |
+ for x in expected: |
78 |
+ if x == got: |
79 |
+ expected = x |
80 |
+ break |
81 |
elif key in ("unstable_keywords", "needed_p_mask_changes", |
82 |
"unsatisfied_deps") and expected is not None: |
83 |
expected = set(expected) |
84 |
diff --git a/pym/portage/tests/resolver/test_autounmask_use_breakage.py b/pym/portage/tests/resolver/test_autounmask_use_breakage.py |
85 |
new file mode 100644 |
86 |
index 0000000..3654aa6 |
87 |
--- /dev/null |
88 |
+++ b/pym/portage/tests/resolver/test_autounmask_use_breakage.py |
89 |
@@ -0,0 +1,63 @@ |
90 |
+# Copyright 2014 Gentoo Foundation |
91 |
+# Distributed under the terms of the GNU General Public License v2 |
92 |
+ |
93 |
+from portage.tests import TestCase |
94 |
+from portage.tests.resolver.ResolverPlayground import (ResolverPlayground, |
95 |
+ ResolverPlaygroundTestCase) |
96 |
+ |
97 |
+class AutounmaskUseBreakageTestCase(TestCase): |
98 |
+ |
99 |
+ def testAutounmaskUseBreakage(self): |
100 |
+ |
101 |
+ ebuilds = { |
102 |
+ |
103 |
+ "app-misc/A-0" : { |
104 |
+ "EAPI": "5", |
105 |
+ "RDEPEND": "app-misc/D[-foo]", |
106 |
+ }, |
107 |
+ |
108 |
+ "app-misc/B-0" : { |
109 |
+ "EAPI": "5", |
110 |
+ "RDEPEND": "app-misc/D[foo]" |
111 |
+ }, |
112 |
+ |
113 |
+ "app-misc/C-0" : { |
114 |
+ "EAPI": "5", |
115 |
+ "RDEPEND": ">=app-misc/D-1" |
116 |
+ }, |
117 |
+ |
118 |
+ "app-misc/D-0" : { |
119 |
+ "EAPI": "5", |
120 |
+ "IUSE": "foo" |
121 |
+ }, |
122 |
+ |
123 |
+ "app-misc/D-1" : { |
124 |
+ "EAPI": "5", |
125 |
+ "IUSE": "bar" |
126 |
+ }, |
127 |
+ |
128 |
+ } |
129 |
+ |
130 |
+ test_cases = ( |
131 |
+ |
132 |
+ # Bug 510270 |
133 |
+ # _solve_non_slot_operator_slot_conflicts throws |
134 |
+ # IndexError: tuple index out of range |
135 |
+ # due to autounmask USE breakage. |
136 |
+ ResolverPlaygroundTestCase( |
137 |
+ ["app-misc/C", "app-misc/B", "app-misc/A"], |
138 |
+ all_permutations = True, |
139 |
+ success = False, |
140 |
+ ambiguous_slot_collision_solutions = True, |
141 |
+ slot_collision_solutions = [None, []] |
142 |
+ ), |
143 |
+ |
144 |
+ ) |
145 |
+ |
146 |
+ playground = ResolverPlayground(ebuilds=ebuilds, debug=False) |
147 |
+ try: |
148 |
+ for test_case in test_cases: |
149 |
+ playground.run_TestCase(test_case) |
150 |
+ self.assertEqual(test_case.test_success, True, test_case.fail_msg) |
151 |
+ finally: |
152 |
+ playground.cleanup() |
153 |
-- |
154 |
1.8.5.5 |