Always mask the higher version when backtracking due to a slot conflict
authorSebastian Luther <SebastianLuther@gmx.de>
Mon, 20 Sep 2010 06:25:37 +0000 (08:25 +0200)
committerZac Medico <zmedico@gentoo.org>
Mon, 20 Sep 2010 06:34:53 +0000 (23:34 -0700)
pym/_emerge/depgraph.py
pym/portage/tests/resolver/test_backtracking.py

index 529dd2ae9a3262a71889c1991703a6439d663f46..9122232ffd41aed0c7b07c57fd3283bc2bf56921 100644 (file)
@@ -906,21 +906,27 @@ class depgraph(object):
                                                        conflict_atoms = self._dynamic_config._slot_conflict_parent_atoms.intersection(parent_atoms)
                                                        if conflict_atoms:
                                                                parent_atoms = conflict_atoms
-                                               if pkg >= existing_node:
+
+                                               if pkg > existing_node:
+                                                       to_be_masked = pkg
+                                               else:
+                                                       to_be_masked = existing_node
+
+                                               if pkg.cpv == existing_node.cpv:
                                                        # We only care about the parent atoms
                                                        # when they trigger a downgrade.
                                                        parent_atoms = set()
 
                                                self._dynamic_config._runtime_pkg_mask.setdefault(
-                                                       existing_node, {})["slot conflict"] = parent_atoms
+                                                       to_be_masked, {})["slot conflict"] = parent_atoms
                                                self._dynamic_config._need_restart = True
                                                if "--debug" in self._frozen_config.myopts:
                                                        msg = []
                                                        msg.append("")
                                                        msg.append("")
                                                        msg.append("backtracking due to slot conflict:")
-                                                       msg.append("   package: %s" % existing_node)
-                                                       msg.append("      slot: %s" % existing_node.slot_atom)
+                                                       msg.append("   package: %s" % to_be_masked)
+                                                       msg.append("      slot: %s" % to_be_masked.slot_atom)
                                                        msg.append("   parents: %s" % \
                                                                [(str(parent), atom) \
                                                                for parent, atom in parent_atoms])
index d219c6bd55fb709e28e9fbfb0d9fe710cb7a1cb9..91a739aafc3da89ad5a5023b592a9d9754daa40b 100644 (file)
@@ -29,3 +29,33 @@ class BacktrackingTestCase(TestCase):
                                self.assertEqual(test_case.test_success, True, test_case.fail_msg)
                finally:
                        playground.cleanup()
+
+       def testBacktrackingGoodVersionFirst(self):
+               """
+               When backtracking due to slot conflicts, we masked the version that has been pulled
+               in first. This is not always a good idea. Mask the highest version instead.
+               """
+
+               ebuilds = {
+                       "dev-libs/A-1": { "DEPEND": "=dev-libs/C-1 dev-libs/B" },
+                       "dev-libs/B-1": { "DEPEND": "=dev-libs/C-1" },
+                       "dev-libs/B-2": { "DEPEND": "=dev-libs/C-2" },
+                       "dev-libs/C-1": { },
+                       "dev-libs/C-2": { },
+                       }
+
+               test_cases = (
+                               ResolverPlaygroundTestCase(
+                                       ["dev-libs/A"],
+                                       mergelist = ["dev-libs/C-1", "dev-libs/B-1", "dev-libs/A-1", ],
+                                       success = True),
+                       )
+
+               playground = ResolverPlayground(ebuilds=ebuilds)
+
+               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()