diff options
author | Zac Medico <zmedico@gentoo.org> | 2014-09-19 02:24:58 -0700 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2014-09-19 02:26:15 -0700 |
commit | c81f3f4586b7b6164f5038ac778098911fef9404 (patch) | |
tree | 477e33601c5d752cb3fb07ad73bf908494cffdad | |
parent | _backtrack_depgraph: fix bug #523048 (diff) | |
download | portage-c81f3f4586b7b6164f5038ac778098911fef9404.tar.gz portage-c81f3f4586b7b6164f5038ac778098911fef9404.tar.bz2 portage-c81f3f4586b7b6164f5038ac778098911fef9404.zip |
_solve_..slot_conflicts: fix bug #522084
Fix _solve_non_slot_operator_slot_conflicts to add all parents to the
conflict_graph, even for parents where the atom matches all relevant
nodes. Otherwise, we risk removing all of the matched nodes from the
graph, which would cause a missed update.
X-Gentoo-Bug: 522084
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=522084
Reviewed-by: Alexander Berntsen <bernalex@gentoo.org>
-rw-r--r-- | pym/_emerge/depgraph.py | 14 | ||||
-rw-r--r-- | pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py | 75 |
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() |