From 6c6ac86ee1505015bd5f671e4ae6cdad8d7b53c1 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sun, 25 May 2008 03:59:35 +0000 Subject: Merge the Atom class and dbapi._iter_match() from trunk r10387 and r10394. Everything related to USE deps has been omitted for now. svn path=/main/branches/2.1.2/; revision=10403 --- bin/emerge | 3 +- bin/repoman | 1 + pym/portage.py | 102 +++++++++++++++++++++++++++++------------------------ pym/portage_dep.py | 44 ++++++++++++++++++++--- 4 files changed, 98 insertions(+), 52 deletions(-) diff --git a/bin/emerge b/bin/emerge index fbc797a33..dafb3bb66 100755 --- a/bin/emerge +++ b/bin/emerge @@ -3044,7 +3044,8 @@ class depgraph(object): # List of acceptable packages, ordered by type preference. matched_packages = [] highest_version = None - atom_cp = portage.dep_getkey(atom) + atom = portage_dep.Atom(atom) + atom_cp = atom.cp existing_node = None myeb = None usepkgonly = "--usepkgonly" in self.myopts diff --git a/bin/repoman b/bin/repoman index f1735dc42..9f48a1536 100755 --- a/bin/repoman +++ b/bin/repoman @@ -1709,6 +1709,7 @@ for x in scanlist: is_blocker = atom.startswith("!") if is_blocker: atom = token.lstrip("!") + atom = portage_dep.Atom(atom) if mytype == "DEPEND" and \ not is_blocker and \ not inherited_java_eclass and \ diff --git a/pym/portage.py b/pym/portage.py index 75301819b..a4f17a234 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -5725,8 +5725,15 @@ def dep_expand(mydep, mydb=None, use_cache=1, settings=None): myindex = orig_dep.index(mydep) prefix = orig_dep[:myindex] postfix = orig_dep[myindex+len(mydep):] - return prefix + cpv_expand( - mydep, mydb=mydb, use_cache=use_cache, settings=settings) + postfix + expanded = cpv_expand(mydep, mydb=mydb, + use_cache=use_cache, settings=settings) + try: + return portage_dep.Atom(prefix + expanded + postfix) + except portage.exception.InvalidAtom: + # Missing '=' prefix is allowed for backward compatibility. + if not isvalidatom("=" + prefix + expanded + postfix): + raise + return portage_dep.Atom("=" + prefix + expanded + postfix) def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None, use_cache=1, use_binaries=0, myroot="/", trees=None): @@ -6288,15 +6295,29 @@ class dbapi(object): 'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or [] if mycpv not found' raise NotImplementedError - def match(self,origdep,use_cache=1): + def match(self, origdep, use_cache=1): + """Given a dependency, try to find packages that match + Args: + origdep - Depend atom + use_cache - Boolean indicating if we should use the cache or not + NOTE: Do we ever not want the cache? + Returns: + a list of packages that match origdep + """ mydep = dep_expand(origdep, mydb=self, settings=self.settings) - mykey=dep_getkey(mydep) - mylist = match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache)) - myslot = portage_dep.dep_getslot(mydep) - if myslot is not None: - mylist = [cpv for cpv in mylist \ - if self.aux_get(cpv, ["SLOT"])[0] == myslot] - return mylist + return list(self._iter_match(mydep, + self.cp_list(mydep.cp, use_cache=use_cache))) + + def _iter_match(self, atom, cpv_iter): + cpv_iter = match_from_list(atom, cpv_iter) + if atom.slot: + cpv_iter = self._iter_match_slot(atom, cpv_iter) + return cpv_iter + + def _iter_match_slot(self, atom, cpv_iter): + for cpv in cpv_iter: + if self.aux_get(cpv, ["SLOT"])[0] == atom.slot: + yield cpv def match2(self,mydep,mykey,mylist): writemsg("DEPRECATED: dbapi.match2\n") @@ -6795,13 +6816,8 @@ class vardbapi(dbapi): if self.matchcache.has_key(mycat): del self.mtdircache[mycat] del self.matchcache[mycat] - mymatch = match_from_list(mydep, - self.cp_list(mykey, use_cache=use_cache)) - myslot = portage_dep.dep_getslot(mydep) - if myslot is not None: - mymatch = [cpv for cpv in mymatch \ - if self.aux_get(cpv, ["SLOT"])[0] == myslot] - return mymatch + return list(self._iter_match(mydep, + self.cp_list(mydep.cp, use_cache=use_cache))) try: curmtime=os.stat(self.root+VDB_PATH+"/"+mycat)[stat.ST_MTIME] except (IOError, OSError): @@ -6812,11 +6828,8 @@ class vardbapi(dbapi): self.mtdircache[mycat]=curmtime self.matchcache[mycat]={} if not self.matchcache[mycat].has_key(mydep): - mymatch=match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache)) - myslot = portage_dep.dep_getslot(mydep) - if myslot is not None: - mymatch = [cpv for cpv in mymatch \ - if self.aux_get(cpv, ["SLOT"])[0] == myslot] + mymatch = list(self._iter_match(mydep, + self.cp_list(mydep.cp, use_cache=use_cache))) self.matchcache[mycat][mydep]=mymatch return self.matchcache[mycat][mydep][:] @@ -7819,22 +7832,14 @@ class portdbapi(dbapi): # Find the minimum matching version. This is optimized to # minimize the number of metadata accesses (improves performance # especially in cases where metadata needs to be generated). - if mydep == mykey: - mylist = self.cp_list(mykey) - else: - mylist = match_from_list(mydep, self.cp_list(mykey)) + cpv_iter = iter(self.cp_list(mykey)) + if mydep != mykey: + cpv_iter = self._iter_match(mydep, cpv_iter) myval = "" - if mylist: - if myslot is None: - myval = mylist[0] - else: - for cpv in mylist: - try: - if self.aux_get(cpv, ["SLOT"])[0] == myslot: - myval = cpv - break - except KeyError: - pass # ebuild masked by corruption + for cpv in cpv_iter: + myval = cpv + break + elif level in ("minimum-visible", "bestmatch-visible"): # Find the minimum matching visible version. This is optimized to # minimize the number of metadata accesses (improves performance @@ -7870,24 +7875,27 @@ class portdbapi(dbapi): continue myval = cpv break - elif level=="bestmatch-list": + elif level == "bestmatch-list": #dep match -- find best match but restrict search to sublist - myval=best(match_from_list(mydep,mylist)) - #no point is calling xmatch again since we're not caching list deps - elif level=="match-list": + #no point in calling xmatch again since we're not caching list deps + + myval = best(list(self._iter_match(mydep, mylist))) + elif level == "match-list": #dep match -- find all matches but restrict search to sublist (used in 2nd half of visible()) - myval=match_from_list(mydep,mylist) - elif level=="match-visible": + + myval = list(self._iter_match(mydep, mylist)) + elif level == "match-visible": #dep match -- find all visible matches - myval = match_from_list(mydep, - self.xmatch("list-visible", mykey, mydep=mykey, mykey=mykey)) #get all visible packages, then get the matching ones - elif level=="match-all": + + myval = list(self._iter_match(mydep, + self.xmatch("list-visible", mykey, mydep=mykey, mykey=mykey))) + elif level == "match-all": #match *all* visible *and* masked packages if mydep == mykey: myval = self.cp_list(mykey) else: - myval = match_from_list(mydep, self.cp_list(mykey)) + myval = list(self._iter_match(mydep, self.cp_list(mykey))) else: print "ERROR: xmatch doesn't handle",level,"query!" raise KeyError diff --git a/pym/portage_dep.py b/pym/portage_dep.py index bad51b646..26737d618 100644 --- a/pym/portage_dep.py +++ b/pym/portage_dep.py @@ -20,7 +20,7 @@ import re, sys, types import portage_exception -from portage_exception import InvalidData +from portage_exception import InvalidAtom, InvalidData from portage_versions import catpkgsplit, catsplit, pkgcmp, pkgsplit, ververify def cpvequal(cpv1, cpv2): @@ -274,6 +274,20 @@ def dep_opconvert(deplist): x += 1 return retlist +class Atom(str): + + def __init__(self, s): + str.__init__(self, s) + if not isvalidatom(s, allow_blockers=True): + raise InvalidAtom(s) + self.blocker = "!" == s[:1] + if self.blocker: + s = s[1:] + self.cp = dep_getkey(s) + self.cpv = dep_getcpv(s) + self.slot = dep_getslot(s) + self.operator = get_operator(s) + def get_operator(mydep): """ Return the operator used in a depstring. @@ -289,6 +303,9 @@ def get_operator(mydep): @return: The operator. One of: '~', '=', '>', '<', '=*', '>=', or '<=' """ + operator = getattr(mydep, "operator", None) + if operator is not None: + return operator if mydep: mydep = remove_slot(mydep) if not mydep: @@ -325,6 +342,9 @@ 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: @@ -358,13 +378,20 @@ def dep_getslot(mydep): @rtype: String @return: The slot """ - colon = mydep.rfind(":") + slot = getattr(mydep, "slot", None) + if slot is not None: + return slot + colon = mydep.find(":") if colon != -1: return mydep[colon+1:] return None def remove_slot(mydep): - colon = mydep.rfind(":") + """ + Removes dep components from the right side of an atom: + * slot + """ + colon = mydep.find(":") if colon != -1: mydep = mydep[:colon] return mydep @@ -389,6 +416,10 @@ def isvalidatom(atom, allow_blockers=False): 1) 0 if the atom is invalid 2) 1 if the atom is valid """ + if isinstance(atom, Atom): + if atom.blocker and not allow_blockers: + return 0 + return 1 global _invalid_atom_chars_regexp if _invalid_atom_chars_regexp.search(atom): return 0 @@ -490,6 +521,9 @@ def dep_getkey(mydep): @rtype: String @return: The package category/package-version """ + cp = getattr(mydep, "cp", None) + if cp is not None: + return cp mydep = dep_getcpv(mydep) if mydep and isspecific(mydep): mysplit = catpkgsplit(mydep) @@ -565,8 +599,10 @@ def match_from_list(mydep, candidate_list): """ from portage_util import writemsg - if mydep[0] == "!": + if "!" == mydep[:1]: mydep = mydep[1:] + if not isinstance(mydep, Atom): + mydep = Atom(mydep) mycpv = dep_getcpv(mydep) mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific -- cgit v1.2.3-1-g7c22