Merge the Atom class and dbapi._iter_match() from trunk r10387 and r10394.
authorZac Medico <zmedico@gentoo.org>
Sun, 25 May 2008 03:59:35 +0000 (03:59 -0000)
committerZac Medico <zmedico@gentoo.org>
Sun, 25 May 2008 03:59:35 +0000 (03:59 -0000)
Everything related to USE deps has been omitted for now.

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

bin/emerge
bin/repoman
pym/portage.py
pym/portage_dep.py

index fbc797a334d79843376cb038cdddd7c766bc3d96..dafb3bb66864bf131c9f21fa9003904bd658b1c5 100755 (executable)
@@ -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
index f1735dc4256c5f7dac3cedc46df40f6c7c37c5c8..9f48a1536f9310990c5cbdd7e322b91e118a62a5 100755 (executable)
@@ -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 \
index 75301819baf79fdb04bf5b994652e4ac013a6df1..a4f17a234587eabacaba1f2c0890865c8a179c17 100644 (file)
@@ -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
index bad51b6468f7bf6d6d88a2ceea0760c84c3ca7ba..26737d6187c783c9e7b4dadb979cb784e5aefcea 100644 (file)
@@ -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