Mask packages that don't satisfy all atoms.
authorSebastian Luther <SebastianLuther@gmx.de>
Tue, 5 Oct 2010 18:05:32 +0000 (20:05 +0200)
committerZac Medico <zmedico@gentoo.org>
Tue, 5 Oct 2010 21:44:35 +0000 (14:44 -0700)
This also fixes a logic error in resolver/backtracking/Backtracker._feedback_slot_conflict()

pym/_emerge/depgraph.py
pym/_emerge/resolver/backtracking.py
pym/portage/tests/resolver/test_backtracking.py

index 27c2b475031e8f8df94478c9e4185c71d379bc0c..54f7a18879610938e00962c945c022f271de4578 100644 (file)
@@ -875,8 +875,11 @@ class depgraph(object):
 
                                                backtrack_data = []
                                                all_parents = set()
-                                               # HACK: The ordering of backtrack_data can make
-                                               # a difference here. We choose an order such that
+                                               # The ordering of backtrack_data can make
+                                               # a difference here, because both mask actions may lead
+                                               # to valid, but different, solutions and the one with
+                                               # 'existing_node' masked is usually the better one. Because
+                                               # of that, we choose an order such that
                                                # the backtracker will first explore the choice with
                                                # existing_node masked. The backtracker reverses the
                                                # order twice, so the order it uses is the order shown
@@ -892,26 +895,27 @@ class depgraph(object):
                                                                conflict_atoms = self._dynamic_config._slot_conflict_parent_atoms.intersection(parent_atoms)
                                                                if conflict_atoms:
                                                                        parent_atoms = conflict_atoms
+
                                                        all_parents.update(parent_atoms)
+
+                                                       all_match = True
+                                                       for ppkg, atom in parent_atoms:
+                                                               i = InternalPackageSet(initial_atoms=(atom,))
+                                                               if not i.findAtomForPackage(to_be_masked):
+                                                                       all_match = False
+                                                                       break
+
+                                                       if all_match:
+                                                               # 'to_be_masked' does not violate any parent atom, which means
+                                                               # there is no point in masking it.
+                                                               continue
+
                                                        if to_be_selected >= to_be_masked:
                                                                # We only care about the parent atoms
                                                                # when they trigger a downgrade.
                                                                parent_atoms = set()
                                                        backtrack_data.append((to_be_masked, parent_atoms))
 
-                                               # NOTE: Generally, we prefer to mask the higher
-                                               # version since this solves common cases in which a
-                                               # lower version is needed so that all dependencies
-                                               # will be satisfied (bug #337178). However, if
-                                               # existing_node happens to be installed then we
-                                               # mask that since this is a common case that is
-                                               # triggered when --update is not enabled.
-                                               if existing_node.installed:
-                                                       pass
-                                               elif pkg > existing_node:
-                                                       backtrack_data.reverse()
-                                               to_be_masked = backtrack_data[0][0]
-
                                                self._dynamic_config._backtrack_infos["slot conflict"] = backtrack_data
                                                self._dynamic_config._need_restart = True
                                                if "--debug" in self._frozen_config.myopts:
@@ -921,11 +925,9 @@ class depgraph(object):
                                                        msg.append("backtracking due to slot conflict:")
                                                        msg.append("   first package:  %s" % existing_node)
                                                        msg.append("   second package: %s" % pkg)
-                                                       msg.append("  package to mask: %s" % to_be_masked)
                                                        msg.append("      slot: %s" % pkg.slot_atom)
-                                                       msg.append("   parents: %s" % \
-                                                               [(str(parent), atom) \
-                                                               for parent, atom in all_parents])
+                                                       msg.append("   parents: %s" % ", ".join( \
+                                                               "(%s, '%s')" % (ppkg, atom) for ppkg, atom in all_parents))
                                                        msg.append("")
                                                        writemsg_level("".join("%s\n" % l for l in msg),
                                                                noiselevel=-1, level=logging.DEBUG)
index 9a018cc710a33cc67c824a4719e114e0c883def3..1ffada96f18fb647253e1377d35a131a8683ffc0 100644 (file)
@@ -102,11 +102,8 @@ class Backtracker(object):
                        new_node.depth += 1
                        new_node.mask_steps += 1
                        new_node.terminal = False
-                       for other_pkg, other_parent_atoms in conflict_data:
-                               if other_pkg is pkg:
-                                       continue
-                               new_node.parameter.runtime_pkg_mask.setdefault(
-                                       other_pkg, {})["slot conflict"] = other_parent_atoms
+                       new_node.parameter.runtime_pkg_mask.setdefault(
+                               pkg, {})["slot conflict"] = parent_atoms
                        self._add(new_node)
 
 
index d862d3dc7c3983934da0ff8d104621b87a30cfab..fc493062cb780b27235f3edc196a5e8e61f6024b 100644 (file)
@@ -137,11 +137,6 @@ class BacktrackingTestCase(TestCase):
                An update is missed due to a dependency on an older version.
                """
 
-               # NOTE: This test fails if the order of slot conflict
-               # backtrack_data is reversed inside depgraph._add_pkg().
-               # This may indicate that Backtracker is failing to generate
-               # the appropriate nodes to explore in this case.
-
                ebuilds = {
                        "dev-libs/A-1": { },
                        "dev-libs/A-2": { },