Hi!

I reworked my new search code a bit and factored it out into single patches. I decided to change the interface to:

def getProvides(self, name, flags=None, version=None):
def getRequires(self, name, flags=None, version=None):

to avoid collisions with other methods and to be able to postpone further discussions about deprecation and streamlining of the API to next year. Although the names are not that nice that's probably the best way to go.

yum-prco_helpers.diff was already posted to the list I just add it here for completeness as it is needed by the other patches. The other patches just add the both methods to PackageSackBase and its sub classes.

FYI: I moved the searches on the transaction to the transactioninfo.TransactionData class where they look much better now. There also are .getNewProvides/Requires(), .getOldProvides/Requires() methods with are useful at some places in the depsolver. LocalInstall pkgs will also be handled within the TransactionData which will keep them in a PackageSack for faster searching (will need "Dynamic Indexes" patch).

Patch will follow as soon as I have divided the changes to transactioninfo into 3 different patches. (getProvides, removedmembers, .depends_on->sets)

Comments are welcome.

Florian Festi
? yum-prco_helpers.diff
Index: rpmUtils/miscutils.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/rpmUtils/miscutils.py,v
retrieving revision 1.21
diff -u -r1.21 miscutils.py
--- rpmUtils/miscutils.py	7 Apr 2007 18:23:15 -0000	1.21
+++ rpmUtils/miscutils.py	6 Jun 2007 11:48:28 -0000
@@ -126,10 +126,20 @@
        ex: foo >= 2.1-1"""
     # we only ever get here if we have a versioned prco
     # nameonly shouldn't ever raise it
-    (reqn, reqf, (reqe, reqv, reqr)) = reqtuple
+    #(reqn, reqf, (reqe, reqv, reqr)) = reqtuple
     (n, a, e, v, r) = pkgtuple
-    #simple failures
-    if reqn != n: return 0
+    return rangeCompare(reqtuple, (n, 'EQ', (e, v, r)))
+
+def rangeCompare(reqtuple, provtuple):
+    """returns true if provtuple satisfies reqtuple"""
+    (reqn, reqf, (reqe, reqv, reqr)) = reqtuple
+    (n, f, (e, v, r)) = provtuple
+    if reqn != n:
+        return 0
+
+    if f is None or reqf is None:
+        return 1
+    
     # and you thought we were done having fun
     # if the requested release is left out then we have
     # to remove release from the package prco to make sure the match
@@ -141,19 +151,54 @@
         e = None
     if reqv is None: # just for the record if ver is None then we're going to segfault
         v = None
-        
-    rc = compareEVR((e, v, r), (reqe, reqv, reqr))
-            
+
+    # if we just require foo-version, then foo-version-* will match
+    if r is None:
+        reqr = None
+
+    rc = rpmUtils.miscutils.compareEVR((e, v, r), (reqe, reqv, reqr))
+
+    # does not match unless
     if rc >= 1:
         if reqf in ['GT', 'GE', 4, 12]:
             return 1
+        if reqf in ['EQ', 8]:
+            if f in ['LE', 10]:
+                return 1
     if rc == 0:
-        if reqf in ['GE', 'LE', 'EQ', 8, 10, 12]:
-            return 1
+        if reqf in ['GT', 4]:
+            if f in ['GT', 'GE', 4, 12]:
+                return 1
+        if reqf in ['GE', 12]:
+            if f in ['GT', 'GE', 'EQ', 'LE', 4, 12, 8, 10]:
+                return 1
+        if reqf in ['EQ', 8]:
+            if f in ['EQ', 'GE', 'LE', 8, 12, 10]:
+                return 1
+        if reqf in ['LE', 10]:
+            if f in ['EQ', 'LE', 'LT', 'GE', 8, 10, 2, 12]:
+                return 1
+        if reqf in ['LT', 2]:
+            if f in ['LE', 'LT', 10, 2]:
+                return 1
     if rc <= -1:
-        if reqf in ['LT', 'LE', 2, 10]:
+        if reqf in ['GT', 'GE', 'EQ', 4, 12, 8]:
+            if f in ['GT', 'GE', 4, 12]:
+                return 1
+        if reqf in ['LE', 'LT', 10, 2]:
             return 1
+#                if rc >= 1:
+#                    if reqf in ['GT', 'GE', 4, 12]:
+#                        return 1
+#                if rc == 0:
+#                    if reqf in ['GE', 'LE', 'EQ', 8, 10, 12]:
+#                        return 1
+#                if rc <= -1:
+#                    if reqf in ['LT', 'LE', 2, 10]:
+#                        return 1
+
     return 0
+    
 
 ###########
 # Title: Remove duplicates from a sequence
Index: yum/packages.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/yum/packages.py,v
retrieving revision 1.104
diff -u -r1.104 packages.py
--- yum/packages.py	3 Jun 2007 15:29:05 -0000	1.104
+++ yum/packages.py	6 Jun 2007 11:48:28 -0000
@@ -247,92 +247,44 @@
                         return 1
 
         return 0
-                
+
     def inPrcoRange(self, prcotype, reqtuple):
         """returns true if the package has a the prco that satisfies 
            the reqtuple range, assume false.
            Takes: prcotype, requested prco tuple"""
+        return bool(self.matchingPrcos(prcotype, reqtuple))
+    
+    def matchingPrcos(self, prcotype, reqtuple):
         # we only ever get here if we have a versioned prco
         # nameonly shouldn't ever raise it
         (reqn, reqf, (reqe, reqv, reqr)) = reqtuple
         # however, just in case
         # find the named entry in pkgobj, do the comparsion
+        result = []
         for (n, f, (e, v, r)) in self.returnPrco(prcotype):
-            if reqn == n:
-                # found it
-                if f is None:
-                    return 1
-                if f != 'EQ' and prcotype == 'provides':                
-                    # isn't this odd, it's not 'EQ' and it is a provides
-                    # - it really should be EQ
-                    # use the pkgobj's evr for the comparison
-                    if e is None:
-                        e = self.epoch
-                    if v is None:
-                        v = self.ver
-                    if r is None:
-                        r = self.rel
-                    
-                    #(e, v, r) = (self.epoch, self.ver, self.rel)
-                # and you thought we were done having fun
-                # if the requested release is left out then we have
-                # to remove release from the package prco to make sure the match
-                # is a success - ie: if the request is EQ foo 1:3.0.0 and we have 
-                # foo 1:3.0.0-15 then we have to drop the 15 so we can match
-                if reqr is None:
-                    r = None
-                if reqe is None:
-                    e = None
-                if reqv is None: # just for the record if ver is None then we're going to segfault
-                    v = None
+            if reqn != n:
+                continue
 
-                # if we just require foo-version, then foo-version-* will match
+            if f != 'EQ' and prcotype == 'provides':                
+                # isn't this odd, it's not 'EQ' and it is a provides
+                # - it really should be EQ
+                # use the pkgobj's evr for the comparison
+                if e is None:
+                    e = self.epoch
+                if v is None:
+                    v = self.ver
                 if r is None:
-                    reqr = None
+                    r = self.rel
+                #(e, v, r) = (self.epoch, self.ver, self.rel)
+
+            matched = rpmUtils.miscutils.rangeCompare(
+                reqtuple, (n, f, (e, v, r)))
+            if matched:
+                result.append((n, f, (e, v, r)))
+
+        return result
+
 
-                rc = rpmUtils.miscutils.compareEVR((e, v, r), (reqe, reqv, reqr))
-                
-                # does not match unless
-                if rc >= 1:
-                    if reqf in ['GT', 'GE', 4, 12]:
-                        return 1
-                    if reqf in ['EQ', 8]:
-                        if f in ['LE', 10]:
-                            return 1
-                if rc == 0:
-                    if reqf in ['GT', 4]:
-                        if f in ['GT', 'GE', 4, 12]:
-                            return 1
-                    if reqf in ['GE', 12]:
-                        if f in ['GT', 'GE', 'EQ', 'LE', 4, 12, 8, 10]:
-                            return 1
-                    if reqf in ['EQ', 8]:
-                        if f in ['EQ', 'GE', 'LE', 8, 12, 10]:
-                            return 1
-                    if reqf in ['LE', 10]:
-                        if f in ['EQ', 'LE', 'LT', 'GE', 8, 10, 2, 12]:
-                            return 1
-                    if reqf in ['LT', 2]:
-                        if f in ['LE', 'LT', 10, 2]:
-                            return 1
-                if rc <= -1:
-                    if reqf in ['GT', 'GE', 'EQ', 4, 12, 8]:
-                        if f in ['GT', 'GE', 4, 12]:
-                            return 1
-                    if reqf in ['LE', 'LT', 10, 2]:
-                        return 1
-                
-                
-#                if rc >= 1:
-#                    if reqf in ['GT', 'GE', 4, 12]:
-#                        return 1
-#                if rc == 0:
-#                    if reqf in ['GE', 'LE', 'EQ', 8, 10, 12]:
-#                        return 1
-#                if rc <= -1:
-#                    if reqf in ['LT', 'LE', 2, 10]:
-#                        return 1
-        return 0
         
     def returnChangelog(self):
         """return changelog entries"""
Index: yum/rpmsack.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/yum/rpmsack.py,v
retrieving revision 1.46
diff -u -r1.46 rpmsack.py
--- yum/rpmsack.py	26 Apr 2007 15:30:14 -0000	1.46
+++ yum/rpmsack.py	14 Jun 2007 09:12:35 -0000
@@ -379,7 +379,7 @@
         # Can't support this now
         raise NotImplementedError
 
-    def whatProvides(self, name, flags, version):
+    def getProvides(self, name, flags=None, version=None):
         """searches the rpmdb for what provides the arguments
            returns a list of pkgtuples of providing packages, possibly empty"""
 
@@ -398,24 +398,23 @@
         elif type(version) is types.NoneType:
             r_e = r_v = r_r = None
         
-        defSack = ListPackageSack() # holder for items definitely providing this dep
+        result = { }
         
         for po in pkgs:
             if name[0] == '/' and r_v is None:
-                # file dep add all matches to the defSack
-                defSack.addPackage(po)
+                result[po] = [(name, None, (None, None, None))]
                 continue
+            hits = po.matchingPrcos(
+                'provides', (name, flags, (r_e, r_v, r_r)))
+            if hits:
+                result[po] = hits
+        return result
 
-            if po.checkPrco('provides', (name, flags, (r_e, r_v, r_r))):
-                defSack.addPackage(po)
-
-        returnlist = []
-        for pkg in defSack.returnPackages():
-            returnlist.append(pkg.pkgtup)
-        
-        return returnlist
+    def whatProvides(self, name, flags, version):
+        # XXX deprecate?
+        return [po.pkgtup for po in self.getProvides(name, flags, version)]
 
-    def whatRequires(self, name, flags, version):
+    def getRequires(self, name, flags=None, version=None):
         """searches the rpmdb for what provides the arguments
            returns a list of pkgtuples of providing packages, possibly empty"""
 
@@ -429,23 +428,23 @@
             (r_e, r_v, r_r) = version
         elif type(version) is types.NoneType:
             r_e = r_v = r_r = None
-        
-        defSack = ListPackageSack() # holder for items definitely providing this dep
-        
+
+        result = { }
+
         for po in pkgs:
             if name[0] == '/' and r_v is None:
                 # file dep add all matches to the defSack
-                defSack.addPackage(po)
+                result[po] = [(name, None, (None, None, None))]
                 continue
+            hits = po.matchingPrcos(
+                'requires', (name, flags, (r_e, r_v, r_r)))
+            if hits:
+                result[po] = hits
+        return result
 
-            if po.checkPrco('requires', (name, flags, (r_e, r_v, r_r))):
-                defSack.addPackage(po)
-
-        returnlist = []
-        for pkg in defSack.returnPackages():
-            returnlist.append(pkg.pkgtup)
-        
-        return returnlist    
+    def whatRequires(self, name, flags, version):
+        # XXX deprecate?
+        return [po.pkgtup for po in self.getProvides(name, flags, version)]
             
 def main():
     sack = RPMDBPackageSack('/')
Index: yum/sqlitesack.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/yum/sqlitesack.py,v
retrieving revision 1.99
diff -u -r1.99 sqlitesack.py
--- yum/sqlitesack.py	30 May 2007 21:37:30 -0000	1.99
+++ yum/sqlitesack.py	14 Jun 2007 09:12:23 -0000
@@ -32,6 +32,7 @@
 import warnings
 
 from sqlutils import executeSQL
+import rpmUtils.miscutils
 
 class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase):
     def __init__(self, repo, db_obj):
@@ -210,6 +211,10 @@
         self.filelistsdb = {}
         self.otherdb = {}
         self.excludes = {}
+        self._search_cache = {
+            'provides' : { },
+            'requires' : { },
+            }
 
     def __len__(self):
         for (rep,cache) in self.primarydb.items():
@@ -427,6 +432,74 @@
         
         return pkgs
         
+
+    def _search(self, prcotype, name, flags, version):
+        if flags == 0:
+            flags = None
+        if type(version) in (str, type(None), unicode):
+            req = (name, flags, rpmUtils.miscutils.stringToVersion(
+                version))
+        elif type(version) in (tuple, list): # would this ever be a list?
+            req = (name, flags, version)
+
+        if self._search_cache[prcotype].has_key(req):
+            return self._search_cache[prcotype][req]
+
+        result = { }
+        
+        for (rep,cache) in self.primarydb.items():
+            cur = cache.cursor()
+            executeSQL(cur, "select * from %s where name=?" % prcotype,
+                       (name,))
+            tmp = { }
+            for x in cur:
+                val = (x['name'], x['flags'],
+                       (x['epoch'], x['version'], x['release']))
+                if rpmUtils.miscutils.rangeCompare(req, val):
+                    tmp.setdefault(x['pkgKey'], []).append(val)
+            for pkgKey, hits in tmp.iteritems():
+                executeSQL(cur, "select * from packages where pkgKey=?",
+                           (pkgKey,))
+                x = cur.fetchone()
+                if self._excluded(rep,x['pkgId']):
+                    continue                     
+                result[self.pc(rep,x)] = hits
+                    
+        if prcotype != 'provides' or name[0] != '/':
+            self._search_cache[prcotype][req] = result
+            return result
+
+        matched = 0
+        globs = ['.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$']
+        for thisglob in globs:
+            globc = re.compile(thisglob)
+            if globc.match(name):
+                matched = 1
+
+        if not matched: # if its not in the primary.xml files
+            # search the files.xml file info
+            for pkg in self.searchFiles(name):
+                result[pkg] = [(name, None, None)]
+            self._search_cache[prcotype][req] = result
+            return result
+
+        # If it is a filename, search the primary.xml file info
+        for (rep,cache) in self.primarydb.items():
+            cur = cache.cursor()
+            executeSQL(cur, "select DISTINCT packages.* from files,packages where files.name = ? and files.pkgKey = packages.pkgKey", (name,))
+            for x in cur:
+                if self._excluded(rep,x['pkgId']):
+                    continue
+                result[self.pc(rep,x)] = [(name, None, None)]
+        self._search_cache[prcotype][req] = result
+        return result
+
+    def getProvides(self, name, flags=None, version=None):
+        return self._search("provides", name, flags, version)
+
+    def getRequires(self, name, flags=None, version=None):
+        return self._search("requires", name, flags, version)
+        
     
     def searchPrco(self, name, prcotype):
         """return list of packages having prcotype name (any evr and flag)"""
Index: yum/packageSack.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/yum/packageSack.py,v
retrieving revision 1.29
diff -u -r1.29 packageSack.py
--- yum/packageSack.py	4 Mar 2007 21:45:16 -0000	1.29
+++ yum/packageSack.py	14 Jun 2007 09:12:50 -0000
@@ -65,6 +65,14 @@
         (n,a,e,v,r) = pkgtup
         return self.searchNevra(name=n, arch=a, epoch=e, ver=v, rel=r)
         
+    def getProvides(self, name, flags=None, version=None):
+        """return dict { packages -> list of matching provides }"""
+        raise NotImplementedError()
+
+    def getRequires(self, name, flags=None, version=None):
+        """return dict { packages -> list of matching requires }"""
+        raise NotImplementedError()
+        
     def searchRequires(self, name):
         """return list of package requiring the name (any evr and flag)"""
         raise NotImplementedError()
@@ -231,6 +239,14 @@
         """return list of pkgobjects matching the nevra requested"""
         return self._computeAggregateListResult("searchNevra", name, epoch, ver, rel, arch)
 
+    def getProvides(self, name, flags=None, version=None):
+        """return dict { packages -> list of matching provides }"""
+        return self._computeAggregateDictResult("getProvides", name, flags, version)
+
+    def getRequires(self, name, flags=None, version=None):
+        """return dict { packages -> list of matching requires }"""
+        return self._computeAggregateDictResult("getRequires", name, flags, version)
+
     def searchRequires(self, name):
         """return list of package requiring the name (any evr and flag)"""
         return self._computeAggregateListResult("searchRequires", name)
@@ -435,6 +451,26 @@
         else:
             return []
         
+    def getProvides(self, name, flags=None, version=None):
+        """return dict { packages -> list of matching provides }"""
+        self._checkIndexes(failure='build')
+        result = { }
+        for po in self.provides.get(name, []):
+            hits = po.matchingPrcos('provides', (name, flags, version))
+            if hits:
+                result[po] = hits
+        return result
+
+    def getRequires(self, name, flags=None, version=None):
+        """return dict { packages -> list of matching requires }"""
+        self._checkIndexes(failure='build')
+        result = { }
+        for po in self.requires.get(name, []):
+            hits = po.matchingPrcos('requires', (name, flags, version))
+            if hits:
+                result[po] = hits
+        return result
+        
     def searchRequires(self, name):
         """return list of package requiring the name (any evr and flag)"""
         self._checkIndexes(failure='build')        
_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel

Reply via email to