Merged from trunk -r14256:14270
authorFabian Groffen <grobian@gentoo.org>
Wed, 16 Sep 2009 18:12:43 +0000 (18:12 -0000)
committerFabian Groffen <grobian@gentoo.org>
Wed, 16 Sep 2009 18:12:43 +0000 (18:12 -0000)
   | 14259   | Use a regular expression for cpv_getkey(), and fall back to  |
   | zmedico | legacy code if no match is found.                            |

   | 14261   | Insice match_from_list(), use remove_slot() instead of       |
   | zmedico | dep_getcpv() where appropriate.                              |

   | 14262   | Make dep_getcpv() use Atom, and fall back to legacy code for |
   | zmedico | backward compat.                                             |

   | 14264   | Simplify cpv_getkey() by just calling dep_getkey('=' +       |
   | zmedico | mycpv).                                                      |

   | 14269   | Reimplement the code from bug #283795 so that indirect deps  |
   | zmedico | are preserved for later use. TODO: Write code to add         |
   |         | selected indirect virtual deps to the graph. This will take  |
   |         | advantage of circular dependency avoidance that's done by    |
   |         | dep_zapdeps.                                                 |

   | 14270   | When _expand_new_virtuals() is called by repoman, skip       |
   | zmedico | expansion of new-style virtuals.                             |

svn path=/main/branches/prefix/; revision=14276

pym/_emerge/depgraph.py
pym/portage/__init__.py
pym/portage/dep.py

index 9b59e41576f51658b1fa96725790ca6b8d748b2f..23232d31ea901165fb040f48a2ee2fbdc16c5b05 100644 (file)
@@ -1837,10 +1837,12 @@ class depgraph(object):
                pkgsettings = self._frozen_config.pkgsettings[root]
                if trees is None:
                        trees = self._dynamic_config._filtered_trees
+               atom_graph = digraph()
                if True:
                        try:
                                if parent is not None:
                                        trees[root]["parent"] = parent
+                                       trees[root]["atom_graph"] = atom_graph
                                if priority is not None:
                                        trees[root]["priority"] = priority
                                if not strict:
@@ -1851,12 +1853,26 @@ class depgraph(object):
                        finally:
                                if parent is not None:
                                        trees[root].pop("parent")
+                                       trees[root].pop("atom_graph")
                                if priority is not None:
                                        trees[root].pop("priority")
                                portage.dep._dep_check_strict = True
                        if not mycheck[0]:
                                raise portage.exception.InvalidDependString(mycheck[1])
+               if parent is None:
                        selected_atoms = mycheck[1]
+               else:
+                       if parent.cpv in atom_graph:
+                               # TODO: Write code to add selected indirect virtual deps to
+                               # the graph. This will take advantage of circular dependency
+                               # avoidance that's done by dep_zapdeps. For now, only return
+                               # direct deps here, since we don't want to distort the
+                               # dependency graph by mixing indirect deps.
+                               direct_deps = set(atom_graph.child_nodes(parent.cpv))
+                               selected_atoms = [atom for atom in mycheck[1] \
+                                       if atom in direct_deps]
+                       else:
+                               selected_atoms = []
                return selected_atoms
 
        def _show_unsatisfied_dep(self, root, atom, myparent=None, arg=None):
index ef3910c44bc0447274a050f5e2f5765743dd9014..d6ca5aebd8646f1aa85428f56e4fa359aae72cc9 100644 (file)
@@ -7441,6 +7441,10 @@ def dep_virtual(mysplit, mysettings):
                                newsplit.append(x)
        return newsplit
 
+# According to GLEP 37, RDEPEND is the only dependency type that is valid
+# for new-style virtuals. Repoman should enforce this.
+_virt_dep_keys = ("RDEPEND",)
+
 def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
        trees=None, use_mask=None, use_force=None, **kwargs):
        """Recursively expand new-style virtuals so as to collapse one or more
@@ -7452,15 +7456,21 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
        the matches are sorted from highest to lowest versions and the atom is
        expanded to || ( highest match ... lowest match )."""
        newsplit = []
-       # According to GLEP 37, RDEPEND is the only dependency type that is valid
-       # for new-style virtuals.  Repoman should enforce this.
-       dep_keys = ["RDEPEND", "DEPEND", "PDEPEND"]
        mytrees = trees[myroot]
        portdb = mytrees["porttree"].dbapi
+       atom_graph = mytrees.get("atom_graph")
        parent = mytrees.get("parent")
-       eapi = mytrees.get("eapi")
-       if eapi is None and parent is not None:
-               eapi = parent.metadata["EAPI"]
+       virt_parent = mytrees.get("virt_parent")
+       virt_eapi = mytrees.get("virt_eapi")
+       parent_cpv = None
+       eapi = None
+       if parent is not None:
+               if virt_parent is not None:
+                       parent_cpv = virt_parent
+                       eapi = virt_eapi
+               else:
+                       parent_cpv = parent.cpv
+                       eapi = parent.metadata["EAPI"]
        repoman = not mysettings.local_config
        if kwargs["use_binaries"]:
                portdb = trees[myroot]["bintree"].dbapi
@@ -7517,6 +7527,8 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                mykey = dep_getkey(x)
                if not mykey.startswith("virtual/"):
                        newsplit.append(x)
+                       if parent_cpv is not None:
+                               atom_graph.add(x, parent_cpv)
                        continue
                mychoices = myvirtuals.get(mykey, [])
                isblocker = x.startswith("!")
@@ -7525,7 +7537,26 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                        # the un-expanded virtual atom is more useful for
                        # maintaining a cache of blocker atoms.
                        newsplit.append(x)
+                       if parent_cpv is not None:
+                               atom_graph.add(x, parent_cpv)
                        continue
+
+               if repoman:
+                       if portdb.cp_list(x.cp):
+                               newsplit.append(x)
+                       else:
+                               # TODO: Add PROVIDE check for repoman.
+                               a = []
+                               for y in mychoices:
+                                       a.append(portage.dep.Atom(x.replace(mykey, str(y.cp), 1)))
+                               if not a:
+                                       newsplit.append(x)
+                               elif len(a) == 1:
+                                       newsplit.append(a[0])
+                               else:
+                                       newsplit.append(['||'] + a)
+                       continue
+
                match_atom = x
                pkgs = []
                matches = portdb.match(match_atom)
@@ -7542,12 +7573,14 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                        # atom is not eliminated here since it may still represent a
                        # dependency that needs to be satisfied.
                        newsplit.append(x)
+                       if parent_cpv is not None:
+                               atom_graph.add(x, parent_cpv)
                        continue
 
                a = []
                for y in pkgs:
                        cpv, pv_split, db = y
-                       depstring = " ".join(db.aux_get(cpv, dep_keys))
+                       depstring = " ".join(db.aux_get(cpv, _virt_dep_keys))
                        pkg_kwargs = kwargs.copy()
                        if repoman:
                                pass
@@ -7560,34 +7593,34 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                print _("Virtual Depstring:"), depstring
 
                        # Set EAPI used for validation in dep_check() recursion.
-                       virtual_eapi, = db.aux_get(cpv, ["EAPI"])
-                       prev_eapi = mytrees.get("eapi")
-                       mytrees["eapi"] = virtual_eapi
+                       new_eapi, = db.aux_get(cpv, ["EAPI"])
+                       mytrees["virt_eapi"] = new_eapi
+                       mytrees["virt_parent"] = cpv
 
                        try:
                                mycheck = dep_check(depstring, mydbapi, mysettings,
                                        myroot=myroot, trees=trees, **pkg_kwargs)
                        finally:
                                # Restore previous EAPI after recursion.
-                               if prev_eapi is not None:
-                                       mytrees["eapi"] = prev_eapi
+                               if virt_parent is not None:
+                                       mytrees["virt_parent"] = virt_parent
+                                       mytrees["virt_eapi"] = virt_eapi
                                else:
-                                       del mytrees["eapi"]
+                                       del mytrees["virt_parent"]
+                                       del mytrees["virt_eapi"]
 
                        if not mycheck[0]:
                                raise portage.exception.ParseError(
                                        "%s: %s '%s'" % (y[0], mycheck[1], depstring))
 
                        # pull in the new-style virtual
-                       mycheck[1].append(dep.Atom('=' + cpv))
+                       virt_atom = dep.Atom('=' + cpv)
+                       mycheck[1].append(virt_atom)
                        a.append(mycheck[1])
+                       if parent_cpv is not None:
+                               atom_graph.add(virt_atom, parent_cpv)
                # Plain old-style virtuals.  New-style virtuals are preferred.
                if not pkgs:
-                       if repoman:
-                               # TODO: Add PROVIDE check for repoman.
-                               for y in mychoices:
-                                       a.append(portage.dep.Atom(x.replace(mykey, str(y.cp), 1)))
-                       else:
                                for y in mychoices:
                                        new_atom = portage.dep.Atom(
                                                x.replace(mykey, dep_getkey(y), 1))
@@ -7597,6 +7630,8 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                        if matches and mykey in \
                                                portdb.aux_get(matches[-1], ['PROVIDE'])[0].split():
                                                a.append(new_atom)
+                                               if parent_cpv is not None:
+                                                       atom_graph.add(new_atom, parent_cpv)
 
                if not a and mychoices:
                        # Check for a virtual package.provided match.
@@ -7605,9 +7640,13 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                if match_from_list(new_atom,
                                        pprovideddict.get(new_atom.cp, [])):
                                        a.append(new_atom)
+                                       if parent_cpv is not None:
+                                               atom_graph.add(new_atom, parent_cpv)
 
                if not a:
                        newsplit.append(x)
+                       if parent_cpv is not None:
+                               atom_graph.add(x, parent_cpv)
                elif len(a) == 1:
                        newsplit.append(a[0])
                else:
@@ -7951,29 +7990,6 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
                # the dependencies of an installed package.
                return [0, _("Invalid atom: '%s'") % (e,)]
 
-       # In order to optimize selection of virtual dependencies,
-       # _expand_new_virtuals() performs a lookahead on new-style
-       # virtuals, which causes expansion of indirect virtual deps.
-       # In order to avoid distorting the dependency graph, we want
-       # to discard the expanded indirect virtual deps after they
-       # are no longer needed, and return only the atom which
-       # corresponds to the virtual package which has been chosen
-       # to satisfy a direct dependency.
-       if ' ' not in depstring:
-               # The depgraph only passes in one virtual atom at at time
-               # here, since it delays evaluation of disjuctive deps.
-               try:
-                       virt_atom = dep.Atom(depstring)
-               except exception.InvalidAtom:
-                       pass
-               else:
-                       # Note: selected_atoms[-1] comes from the following line
-                       # inside _expand_new_virtuals():
-                       #   mycheck[1].append(dep.Atom('=' + cpv))
-                       if virt_atom.cp.startswith('virtual/') and \
-                               selected_atoms and selected_atoms[-1].cp == virt_atom.cp:
-                               selected_atoms = [selected_atoms[-1]]
-
        return [1, selected_atoms]
 
 def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
@@ -8019,17 +8035,7 @@ def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
        return deplist
 
 def cpv_getkey(mycpv):
-       myslash=mycpv.split("/")
-       mysplit=pkgsplit(myslash[-1])
-       if mysplit is None:
-               return None
-       mylen=len(myslash)
-       if mylen==2:
-               return myslash[0]+"/"+mysplit[0]
-       elif mylen==1:
-               return mysplit[0]
-       else:
-               return mysplit
+       return dep.dep_getkey('=' + mycpv)
 
 def key_expand(mykey, mydb=None, use_cache=1, settings=None):
        mysplit=mykey.split("/")
index 929e31dbe65f3d00c6891541e8bdba99379b2514..b54c528fa0c540609e02ce3d709dda16c66c0a84 100644 (file)
@@ -738,8 +738,6 @@ def get_operator(mydep):
 
        return operator
 
-_dep_getcpv_cache = {}
-
 def dep_getcpv(mydep):
        """
        Return the category-package-version with any operators/slot specifications stripped off
@@ -753,13 +751,13 @@ def dep_getcpv(mydep):
        @rtype: String
        @return: The depstring with the operator removed
        """
-       cpv = getattr(mydep, "cpv", None)
-       if cpv is not None:
-               return cpv
-       global _dep_getcpv_cache
-       retval = _dep_getcpv_cache.get(mydep, None)
-       if retval is not None:
-               return retval
+
+       try:
+               return Atom(mydep).cpv
+       except InvalidAtom:
+               pass
+
+       # Fall back to legacy code for backward compatibility.
        mydep_orig = mydep
        if mydep:
                mydep = remove_slot(mydep)
@@ -776,7 +774,6 @@ def dep_getcpv(mydep):
                mydep = mydep[2:]
        elif mydep[:1] in "=<>~":
                mydep = mydep[1:]
-       _dep_getcpv_cache[mydep_orig] = mydep
        return mydep
 
 def dep_getslot(mydep):
@@ -1122,7 +1119,7 @@ def match_from_list(mydep, candidate_list):
                for x in candidate_list:
                        xcpv = getattr(x, "cpv", None)
                        if xcpv is None:
-                               xcpv = dep_getcpv(x)
+                               xcpv = remove_slot(x)
                        if not cpvequal(xcpv, mycpv):
                                continue
                        mylist.append(x)