From 963efa6fcf1e61d836d5292c88500a7c032cf46e Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 18 Sep 2014 16:16:13 -0700 Subject: [PATCH] _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 --- pym/_emerge/depgraph.py | 14 ++-- .../test_solve_non_slot_operator_slot_conflicts.py | 74 ++++++++++++++++++++++ 2 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 6332733..7bb5252 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1171,12 +1171,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). @@ -1188,9 +1191,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 0000000..ecda28e --- /dev/null +++ b/pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py @@ -0,0 +1,74 @@ +# 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() -- 1.8.5.5