From 94130821ab21186aeca7c514236a60acf6a71082 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 29 Jul 2013 22:04:26 -0700 Subject: [PATCH] Pull in new slots when appropriate, bug #478188. --- pym/_emerge/depgraph.py | 27 +++++++++++++++ pym/portage/dep/dep_check.py | 33 ++++++++++++++++--- pym/portage/tests/resolver/test_or_choices.py | 16 ++++++++- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index a7316f018..c1f1ab051 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -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( diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 48df86937..034985391 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -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: diff --git a/pym/portage/tests/resolver/test_or_choices.py b/pym/portage/tests/resolver/test_or_choices.py index 3bc67bca2..ca021123e 100644 --- a/pym/portage/tests/resolver/test_or_choices.py +++ b/pym/portage/tests/resolver/test_or_choices.py @@ -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 = []), ) -- 2.26.2