In depgraph.create(), don't ignore direct circular dependencies
authorZac Medico <zmedico@gentoo.org>
Mon, 22 Oct 2007 18:49:02 +0000 (18:49 -0000)
committerZac Medico <zmedico@gentoo.org>
Mon, 22 Oct 2007 18:49:02 +0000 (18:49 -0000)
anymore since altlist() is able to handle it properly in cases
where the dependency is satisfied. If the dep is unsatisfied
then it can not be ignored. (trunk r8225)

Allow the depgraph to add old-style virtual providers but prefer
any pre-existing providers over new ones that are added. This
prevents things like ghc-6.4.2 from selecting itself to satisfy
it's own virtual/ghc dependency (creating a circular dependency)
in cases where it should select the default ghc-bin provider.
(trunk r8185:8187)

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

bin/emerge
pym/portage.py

index 6ce75d5c5ef0816ba73462aebec2928b6f3df6c8..3ce12f1d6aa6c12bc99e3a0141b809376106e8b6 100755 (executable)
@@ -1350,14 +1350,13 @@ class depgraph:
                        if existing_node:
                                e_type, myroot, e_cpv, e_status = existing_node
                                if mykey == e_cpv:
-                                       # The existing node can be reused.
-                                       if existing_node != myparent:
-                                               # Refuse to make a node depend on itself so that
-                                               # we don't create a bogus circular dependency
-                                               # in self.altlist().
-                                               self._parent_child_digraph.add(existing_node, myparent)
-                                               self.digraph.addnode(existing_node, myparent,
-                                                       priority=priority)
+                                       # The existing node can be reused. It's okay for a
+                                       # node to depend on itself here if priority.satisfied
+                                       # is True, otherwise it is a circular dependency that
+                                       # can not be ignored.
+                                       self._parent_child_digraph.add(existing_node, myparent)
+                                       self.digraph.addnode(existing_node, myparent,
+                                               priority=priority)
                                        return 1
                                else:
                                        if jbigkey in self._slot_collision_nodes:
@@ -1401,6 +1400,22 @@ class depgraph:
                                self.digraph.addnode(jbigkey, myparent,
                                        priority=priority)
 
+                       if mytype != "installed":
+                               # Allow this package to satisfy old-style virtuals in case it
+                               # doesn't already. Any pre-existing providers will be preferred
+                               # over this one.
+                               try:
+                                       pkgsettings.setinst(mykey, metadata)
+                                       # For consistency, also update the global virtuals.
+                                       settings = self.roots[myroot].settings
+                                       settings.unlock()
+                                       settings.setinst(mykey, metadata)
+                                       settings.lock()
+                               except portage.exception.InvalidDependString, e:
+                                       show_invalid_depstring_notice(jbigkey, metadata["PROVIDE"], str(e))
+                                       del e
+                                       return 0
+
                if arg:
                        self._set_nodes.add(jbigkey)
 
@@ -1770,34 +1785,6 @@ class depgraph:
                        if depstring in self._set_atoms:
                                self._pprovided_args.append((arg, depstring))
 
-               if myparent:
-                       # The parent is added after it's own dep_check call so that it
-                       # isn't allowed to satisfy a direct bootstrap dependency on itself
-                       # via an old-style virtual.  This isn't a problem with new-style
-                       # virtuals, which are preferenced in dep_zapdeps by looking only at
-                       # the depstring, vdb, and available packages.
-
-                       p_type, p_root, p_key, p_status = myparent
-                       if p_status == "merge":
-                               # Update old-style virtuals if this package provides any.
-                               # These are needed for dep_virtual calls inside dep_check.
-                               p_db = self.mydbapi[p_root] # contains cached metadata
-                               if myparent in self._slot_collision_nodes:
-                                       # The metadata isn't cached due to the slot collision.
-                                       p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
-                               try:
-                                       self.pkgsettings[p_root].setinst(p_key, p_db)
-                                       # For consistency, also update the global virtuals.
-                                       settings = self.roots[p_root].settings
-                                       settings.unlock()
-                                       settings.setinst(p_key, p_db)
-                                       settings.lock()
-                               except portage_exception.InvalidDependString, e:
-                                       provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
-                                       show_invalid_depstring_notice(myparent, provide, str(e))
-                                       del e
-                                       return 0
-
                if "--debug" in self.myopts:
                        print "Candidates:",mymerge
                for x in mymerge:
index 91bfc3402e088dc97aab146b8b6015b9dd06369c..6a122916717299946e5b2696a5dd2db471f75cb5 100644 (file)
@@ -1005,6 +1005,8 @@ class config:
                self.userVirtuals = {}
                # Virtual negatives from user specifications.
                self.negVirtuals  = {}
+               # Virtuals added by the depgraph via self.setinst().
+               self._depgraphVirtuals = {}
 
                self.user_profile_dir = None
                self.local_config = local_config
@@ -1028,6 +1030,7 @@ class config:
                        self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
                        self.userVirtuals = copy.deepcopy(clone.userVirtuals)
                        self.negVirtuals  = copy.deepcopy(clone.negVirtuals)
+                       self._depgraphVirtuals = copy.deepcopy(clone._depgraphVirtuals)
 
                        self.use_defs = copy.deepcopy(clone.use_defs)
                        self.usemask  = copy.deepcopy(clone.usemask)
@@ -1859,12 +1862,17 @@ class config:
                if len(self.virtuals) == 0:
                        self.getvirtuals()
                # Grab the virtuals this package provides and add them into the tree virtuals.
-               provides = mydbapi.aux_get(mycpv, ["PROVIDE"])[0]
+               if isinstance(mydbapi, dict):
+                       provides = mydbapi["PROVIDE"]
+               else:
+                       provides = mydbapi.aux_get(mycpv, ["PROVIDE"])[0]
                if not provides:
                        return
                if isinstance(mydbapi, portdbapi):
                        self.setcpv(mycpv, mydb=mydbapi)
                        myuse = self["USE"]
+               elif isinstance(mydbapi, dict):
+                       myuse = mydbapi["USE"]
                else:
                        myuse = mydbapi.aux_get(mycpv, ["USE"])[0]
                virts = flatten(portage_dep.use_reduce(portage_dep.paren_reduce(provides), uselist=myuse.split()))
@@ -1873,10 +1881,10 @@ class config:
                cp = dep_getkey(mycpv)
                for virt in virts:
                        virt = dep_getkey(virt)
-                       providers = self.treeVirtuals.get(virt)
+                       providers = self._depgraphVirtuals.get(virt)
                        if providers is None:
                                providers = []
-                               self.treeVirtuals[virt] = providers
+                               self._depgraphVirtuals[virt] = providers
                        if cp not in providers:
                                providers.append(cp)
                                modified = True
@@ -2216,7 +2224,7 @@ class config:
                                        ptVirtuals[virt].append(cp)
 
                virtuals = stack_dictlist([ptVirtuals, self.treeVirtuals,
-                       self.dirVirtuals])
+                       self.dirVirtuals, self._depgraphVirtuals])
                return virtuals
 
        def __delitem__(self,mykey):