From: Fabian Groffen Date: Wed, 16 Sep 2009 18:12:43 +0000 (-0000) Subject: Merged from trunk -r14256:14270 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=706e2a0d07c6cbba15bfe0fd7f622931c0e5c000;p=portage.git Merged from trunk -r14256:14270 | 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 --- diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 9b59e4157..23232d31e 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -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): diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index ef3910c44..d6ca5aebd 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -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("/") diff --git a/pym/portage/dep.py b/pym/portage/dep.py index 929e31dbe..b54c528fa 100644 --- a/pym/portage/dep.py +++ b/pym/portage/dep.py @@ -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)