Pull in new slots when appropriate, bug #478188.
authorZac Medico <zmedico@gentoo.org>
Tue, 30 Jul 2013 05:04:26 +0000 (22:04 -0700)
committerZac Medico <zmedico@gentoo.org>
Tue, 30 Jul 2013 05:04:26 +0000 (22:04 -0700)
pym/_emerge/depgraph.py
pym/portage/dep/dep_check.py
pym/portage/tests/resolver/test_or_choices.py

index a7316f0185fdc73660727b5ff8c0d5553a8dc451..c1f1ab051ba2c9dfa7990c0892837347bcd060d3 100644 (file)
@@ -454,6 +454,7 @@ class _dynamic_depgraph_config(object):
                        self._graph_trees[myroot]["vartree"]    = graph_tree
                        self._graph_trees[myroot]["graph_db"]   = graph_tree.dbapi
                        self._graph_trees[myroot]["graph"]      = self.digraph
+                       self._graph_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg
                        def filtered_tree():
                                pass
                        filtered_tree.dbapi = _dep_check_composite_db(depgraph, myroot)
@@ -480,6 +481,7 @@ class _dynamic_depgraph_config(object):
                        self._filtered_trees[myroot]["graph"]    = self.digraph
                        self._filtered_trees[myroot]["vartree"] = \
                                depgraph._frozen_config.trees[myroot]["vartree"]
+                       self._filtered_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg
 
                        dbs = []
                        #               (db, pkg_type, built, installed, db_keys)
@@ -4314,6 +4316,31 @@ class depgraph(object):
 
                return not arg
 
+       def _want_update_pkg(self, parent, pkg):
+               arg_atoms = None
+               try:
+                       arg_atoms = list(self._iter_atoms_for_pkg(pkg))
+               except InvalidDependString:
+                       if not pkg.installed:
+                               # should have been masked before it was selected
+                               raise
+
+               depth = parent.depth or 0
+               depth += 1
+
+               if arg_atoms:
+                       for arg, atom in arg_atoms:
+                               if arg.reset_depth:
+                                       depth = 0
+                                       break
+
+               deep = self._dynamic_config.myparams.get("deep", 0)
+               update = "--update" in self._frozen_config.myopts
+
+               return (not self._dynamic_config._complete_mode and
+                       (arg_atoms or update) and
+                       not (deep is not True and depth > deep))
+
        def _equiv_ebuild_visible(self, pkg, autounmask_level=None):
                try:
                        pkg_eb = self._pkg(
index 48df869377334d38662a8ec446a8f17d52dd36b8..0349853910889c61fa964ea2e84b8d9947af677c 100644 (file)
@@ -317,6 +317,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
        priority = trees[myroot].get("priority")
        graph_db = trees[myroot].get("graph_db")
        graph    = trees[myroot].get("graph")
+       want_update_pkg = trees[myroot].get("want_update_pkg")
        vardb = None
        if "vartree" in trees[myroot]:
                vardb = trees[myroot]["vartree"].dbapi
@@ -325,6 +326,13 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
        else:
                mydbapi = trees[myroot]["porttree"].dbapi
 
+       try:
+               mydbapi_match_pkgs = mydbapi.match_pkgs
+       except AttributeError:
+               def mydbapi_match_pkgs(atom):
+                       return [mydbapi._pkg_str(cpv, atom.repo)
+                               for cpv in mydbapi.match(atom)]
+
        # Sort the deps into installed, not installed but already 
        # in the graph and other, not installed and not in the graph
        # and other, with values of [[required_atom], availablility]
@@ -348,10 +356,9 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                continue
                        # Ignore USE dependencies here since we don't want USE
                        # settings to adversely affect || preference evaluation.
-                       avail_pkg = mydbapi.match(atom.without_use)
+                       avail_pkg = mydbapi_match_pkgs(atom.without_use)
                        if avail_pkg:
                                avail_pkg = avail_pkg[-1] # highest (ascending order)
-                               avail_pkg = mydbapi._pkg_str(avail_pkg, atom.repo)
                                avail_slot = Atom("%s:%s" % (atom.cp, avail_pkg.slot))
                        if not avail_pkg:
                                all_available = False
@@ -359,7 +366,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                break
 
                        if atom.use:
-                               avail_pkg_use = mydbapi.match(atom)
+                               avail_pkg_use = mydbapi_match_pkgs(atom)
                                if not avail_pkg_use:
                                        all_use_satisfied = False
                                else:
@@ -367,7 +374,6 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                        avail_pkg_use = avail_pkg_use[-1]
                                        if avail_pkg_use != avail_pkg:
                                                avail_pkg = avail_pkg_use
-                                       avail_pkg = mydbapi._pkg_str(avail_pkg, atom.repo)
                                        avail_slot = Atom("%s:%s" % (atom.cp, avail_pkg.slot))
 
                        slot_map[avail_slot] = avail_pkg
@@ -458,8 +464,25 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                                elif all_installed:
                                                        if all_installed_slots:
                                                                preferred_installed.append(this_choice)
-                                                       else:
+                                                       elif parent is None or want_update_pkg is None:
                                                                preferred_any_slot.append(this_choice)
+                                                       else:
+                                                               # When appropriate, prefer a slot that is not
+                                                               # installed yet for bug #478188.
+                                                               want_update = True
+                                                               for slot_atom, avail_pkg in slot_map.items():
+                                                                       # New-style virtuals have zero cost to install.
+                                                                       if slot_atom.startswith("virtual/") or \
+                                                                               vardb.match(slot_atom):
+                                                                               continue
+                                                                       if not want_update_pkg(parent, avail_pkg):
+                                                                               want_update = False
+                                                                               break
+
+                                                               if want_update:
+                                                                       preferred_installed.append(this_choice)
+                                                               else:
+                                                                       preferred_any_slot.append(this_choice)
                                                else:
                                                        preferred_non_installed.append(this_choice)
                                        else:
index 3bc67bca231fc61713d0ffd0f73e412565b1da80..ca021123eb21de8b61daada1ea279e043a7c46bf 100644 (file)
@@ -47,12 +47,26 @@ class OrChoicesTestCase(TestCase):
                world = ["dev-libs/gobject-introspection", "sys-apps/systemd-ui"]
 
                test_cases = (
-                       # Demonstrate that vala:0.20 update is not pulled in, as in bug #478188
+                       # Demonstrate that vala:0.20 update is pulled in, for bug #478188
                        ResolverPlaygroundTestCase(
                                ["@world"],
                                options = {"--update": True, "--deep": True},
                                success=True,
                                all_permutations = True,
+                               mergelist = ['dev-lang/vala-0.20.0']),
+                       # Verify that vala:0.20 is not pulled in without --deep
+                       ResolverPlaygroundTestCase(
+                               ["@world"],
+                               options = {"--update": True},
+                               success=True,
+                               all_permutations = True,
+                               mergelist = []),
+                       # Verify that vala:0.20 is not pulled in without --update
+                       ResolverPlaygroundTestCase(
+                               ["@world"],
+                               options = {"--selective": True, "--deep": True},
+                               success=True,
+                               all_permutations = True,
                                mergelist = []),
                )