aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pym/_emerge/depgraph.py14
-rw-r--r--pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py75
2 files changed, 82 insertions, 7 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index e7ae72002..f4e5a1bf6 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -1172,12 +1172,15 @@ class depgraph(object):
for match in matched:
writemsg_level(" match: %s\n" % match, level=logging.DEBUG, noiselevel=-1)
- if len(matched) == len(conflict):
- # All packages match.
- continue
+ if len(matched) > 1:
+ # Even if all packages match, this parent must still
+ # be added to the conflict_graph. Otherwise, we risk
+ # removing all of these packages from the depgraph,
+ # which could cause a missed update (bug #522084).
+ conflict_graph.add(or_tuple(matched), parent)
elif len(matched) == 1:
conflict_graph.add(matched[0], parent)
- elif len(matched) == 0:
+ else:
# 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).
@@ -1189,9 +1192,6 @@ class depgraph(object):
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)
for pkg in indirect_conflict_pkgs:
for parent, atom in self._dynamic_config._parent_atoms.get(pkg, []):
diff --git a/pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py b/pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py
new file mode 100644
index 000000000..c6024f404
--- /dev/null
+++ b/pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py
@@ -0,0 +1,75 @@
+# 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 SolveNonSlotOperatorSlotConflictsTestCase(TestCase):
+
+ def testSolveNonSlotOperatorSlotConflicts(self):
+
+ ebuilds = {
+
+ "app-misc/A-1" : {
+ "EAPI": "5",
+ "SLOT": "0/1",
+ "PDEPEND": "app-misc/B"
+ },
+
+ "app-misc/A-2" : {
+ "EAPI": "5",
+ "SLOT": "0/2",
+ "PDEPEND": "app-misc/B"
+ },
+
+ "app-misc/B-0" : {
+ "EAPI": "5",
+ "RDEPEND": "app-misc/A:="
+ },
+
+ }
+
+ installed = {
+
+ "app-misc/A-1" : {
+ "EAPI": "5",
+ "SLOT": "0/1",
+ "PDEPEND": "app-misc/B"
+ },
+
+ "app-misc/B-0" : {
+ "EAPI": "5",
+ "RDEPEND": "app-misc/A:0/1="
+ },
+
+ }
+
+ world = ["app-misc/A"]
+
+ test_cases = (
+
+ # bug 522084
+ # In this case, _solve_non_slot_operator_slot_conflicts
+ # removed both versions of app-misc/A from the graph, since
+ # they didn't have any non-conflict parents (except for
+ # @selected which matched both instances). The result was
+ # a missed update.
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True},
+ success = True,
+ mergelist = ['app-misc/A-2', 'app-misc/B-0']
+ ),
+
+ )
+
+ playground = ResolverPlayground(ebuilds=ebuilds,
+ installed=installed, world=world, 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()