From: Zac Medico Date: Mon, 22 Oct 2007 18:49:02 +0000 (-0000) Subject: In depgraph.create(), don't ignore direct circular dependencies X-Git-Tag: v2.1.3.16~9 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=860cd660895829d6915e3dc9643f78e2f12bf3da;p=portage.git In depgraph.create(), don't ignore direct circular dependencies 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 --- diff --git a/bin/emerge b/bin/emerge index 6ce75d5c5..3ce12f1d6 100755 --- a/bin/emerge +++ b/bin/emerge @@ -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: diff --git a/pym/portage.py b/pym/portage.py index 91bfc3402..6a1229167 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -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):