- Improve tracking of correspondence between arguments and packages in the depgraph...
authorZac Medico <zmedico@gentoo.org>
Thu, 28 Jun 2007 01:33:54 +0000 (01:33 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 28 Jun 2007 01:33:54 +0000 (01:33 -0000)
- Cache aux_get() metadata in depgraph.create() and use PROVIDE for matching packages to arguments. (trunk r7064)
- Just use a containment test for matching pprovided args since it works correctly and match_to_list() isn't appropriate for this. (trunk r7065)

svn path=/main/branches/2.1.2/; revision=7066

bin/emerge

index 5c27d4b8880bcb58982b0b3d39d5d872c9c3ec50..039e3e3ad8866737eda707079263be937eba68d1 100755 (executable)
@@ -934,7 +934,8 @@ class depgraph:
                # Maps slot atom to digraph node for all nodes added to the graph.
                self._slot_node_map = {}
                self.mydbapi = {}
-               self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
+               self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND",
+                       "USE", "IUSE", "PROVIDE"]
                self.useFlags = {}
                self.trees = {}
                for myroot in trees:
@@ -978,6 +979,7 @@ class depgraph:
                self.orderedkeys=[]
                self.outdatedpackages=[]
                self._args_atoms = {}
+               self._args_nodes = set()
                self.blocker_digraph = digraph()
                self.blocker_parents = {}
                self._unresolved_blocker_parents = {}
@@ -1108,16 +1110,21 @@ class depgraph:
                # directive, otherwise we add a "merge" directive.
 
                mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
+               metadata = dict(izip(self._mydbapi_keys,
+                       mydbapi.aux_get(mykey, self._mydbapi_keys)))
+               if mytype == "ebuild":
+                       pkgsettings.setcpv(mykey, mydb=portdb)
+                       metadata["USE"] = pkgsettings["USE"]
+                       myuse = pkgsettings["USE"].split()
 
                if not arg and myroot == self.target_root:
-                       cpv_slot = "%s:%s" % (mykey, mydbapi.aux_get(mykey, ["SLOT"])[0])
-                       cp = portage.dep_getkey(mykey)
-                       if cp in self._args_atoms:
-                               arg = portage.best_match_to_list(cpv_slot, self._args_atoms[cp])
-
-               if myuse is None:
-                       self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
-                       myuse = self.pkgsettings[myroot]["USE"].split()
+                       try:
+                               arg = self._get_arg(mykey, metadata)
+                       except portage_exception.InvalidDependString, e:
+                               show_invalid_depstring_notice(tuple(mybigkey+["merge"]),
+                                       metadata["PROVIDE"], str(e))
+                               del e
+                               return 0
 
                merging=1
                if mytype == "installed":
@@ -1140,8 +1147,7 @@ class depgraph:
                                forced_flags.update(pkgsettings.useforce)
                                forced_flags.update(pkgsettings.usemask)
                                old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
-                               iuses = set(filter_iuse_defaults(
-                                       mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
+                               iuses = set(filter_iuse_defaults(metadata["IUSE"].split()))
                                old_iuse = set(filter_iuse_defaults(
                                        vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
                                if self._reinstall_for_flags(
@@ -1155,8 +1161,6 @@ class depgraph:
                jbigkey = tuple(mybigkey)
 
                if addme:
-                       metadata = dict(izip(self._mydbapi_keys,
-                               mydbapi.aux_get(mykey, self._mydbapi_keys)))
                        if merging == 0 and vardbapi.cpv_exists(mykey) and \
                                mytype != "installed":
                                mybigkey[0] = "installed"
@@ -1164,7 +1168,7 @@ class depgraph:
                                jbigkey = tuple(mybigkey)
                                metadata = dict(izip(self._mydbapi_keys,
                                        mydbapi.aux_get(mykey, self._mydbapi_keys)))
-                               myuse = mydbapi.aux_get(mykey, ["USE"])[0].split()
+                               myuse = metadata["USE"].split()
                        slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
                        existing_node = self._slot_node_map[myroot].get(
                                slot_atom, None)
@@ -1222,6 +1226,9 @@ class depgraph:
                                self.digraph.addnode(jbigkey, myparent,
                                        priority=priority)
 
+               if arg:
+                       self._args_nodes.add(jbigkey)
+
                # Do this even when addme is False (--onlydeps) so that the
                # parent/child relationship is always known in case
                # self._show_slot_collision_notice() needs to be called later.
@@ -1245,9 +1252,8 @@ class depgraph:
 
                edepend={}
                depkeys = ["DEPEND","RDEPEND","PDEPEND"]
-               depvalues = mydbapi.aux_get(mykey, depkeys)
-               for i in xrange(len(depkeys)):
-                       edepend[depkeys[i]] = depvalues[i]
+               for k in depkeys:
+                       edepend[k] = metadata[k]
 
                if mytype == "ebuild":
                        if "--buildpkgonly" in self.myopts:
@@ -1554,8 +1560,7 @@ class depgraph:
                        # A provided package has been specified on the command line.  The
                        # package will not be merged and a warning will be displayed.
                        cp = portage.dep_getkey(depstring)
-                       if cp in self._args_atoms and \
-                               portage.match_to_list(depstring, self._args_atoms[cp]):
+                       if cp in self._args_atoms and depstring in self._args_atoms[cp]:
                                self._pprovided_args.append(arg)
 
                if myparent:
@@ -2273,7 +2278,11 @@ class depgraph:
                                                if available:
                                                        newlist.append(myslot_atom)
                mylist = newlist
-               
+
+               for myatom in mylist:
+                       self._args_atoms.setdefault(
+                               portage.dep_getkey(myatom), []).append(myatom)
+
                missing_atoms = []
                for mydep in mylist:
                        try:
@@ -2299,6 +2308,31 @@ class depgraph:
 
                return 1
 
+       def _get_arg(self, cpv, metadata):
+               """Return the best match for a given package from the arguments, or
+               None if there are no matches.  This matches virtual arguments against
+               the PROVIDE metadata.  This can raise an InvalidDependString exception
+               if an error occurs while parsing PROVIDE."""
+               cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
+               cp = portage.dep_getkey(cpv)
+               atoms = self._args_atoms.get(cp)
+               if atoms:
+                       best_match = portage.best_match_to_list(cpv_slot, atoms)
+                       if best_match:
+                               return best_match
+               provides = portage.flatten(portage_dep.use_reduce(
+                       portage_dep.paren_reduce(metadata["PROVIDE"]),
+                       uselist=metadata["USE"].split()))
+               for provide in provides:
+                       provided_cp = portage.dep_getkey(provide)
+                       atoms = self._args_atoms.get(provided_cp)
+                       if atoms:
+                               transformed_atoms = [atom.replace(provided_cp, cp) for atom in atoms]
+                               best_match = portage.best_match_to_list(cpv_slot, transformed_atoms)
+                               if best_match:
+                                       return atoms[transformed_atoms.index(best_match)]
+               return None
+
        def display(self,mylist,verbosity=None):
                if verbosity is None:
                        verbosity = ("--quiet" in self.myopts and 1 or \