On Tue, 2007-01-16 at 23:46 -0500, seth vidal wrote:
> As cracktastic as it may seem - our current globbing mechanism covers
> things like
> 
> [abcdefghijklmno]pkgname.i386

Out of curiosity, how exactly is that used ? I have a hard time coming
up with an example where I would want to glob by character set.

> I don't think the globtolike function you wrote will work in that. We
> use the [] mechanism in mock and for funky excludes.

globtolike goes to show that hours of hacking can easily save you 5
minutes of reading docs. Turns out that sqlite has a (non-ANSI) operator
'glob' which does exactly what is needed here. Updated patch attached; I
can now successfully run 'yum install [xyz]p?f*'.

BTW, packages.parsePackages checks if the pattern contains '[\*,\[,\],
\{,\},\?]' - I think the '{}' shouldn't be in there, they are not
special in globs, and fnmatch.translate just puts them literally into
the regexp.

David

Index: cli.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/cli.py,v
retrieving revision 1.247
diff -u -r1.247 cli.py
--- cli.py	7 Dec 2006 23:25:56 -0000	1.247
+++ cli.py	17 Jan 2007 17:43:31 -0000
@@ -511,7 +511,6 @@
         
         self.doRepoSetup()
         self.doRpmDBSetup()
-        avail = self.pkgSack.returnPackages()
         toBeInstalled = {} # keyed on name
         passToUpdate = [] # list of pkgtups to pass along to updatecheck
 
@@ -524,8 +523,7 @@
                          # no matter what we don't go looking at repos
 
             arglist = [arg]
-            exactmatch, matched, unmatched = parsePackages(avail, arglist, 
-                                                               casematch=1)
+            exactmatch, matched, unmatched = self.pkgSack.parsePackages(arglist)
             if len(unmatched) > 0: # if we get back anything in unmatched, check it for a virtual-provide
                 arg = unmatched[0] #only one in there
                 self.verbose_logger.debug('Checking for virtual provide or file-provide for %s', 
@@ -538,7 +536,7 @@
                     arg = '%s:%s-%s-%s.%s' % (mypkg.epoch, mypkg.name,
                                               mypkg.version, mypkg.release,
                                               mypkg.arch)
-                    emtch, mtch, unmtch = parsePackages(avail, [arg])
+                    emtch, mtch, unmtch = self.pkgSack.parsePackages([arg])
                     exactmatch.extend(emtch)
                     matched.extend(mtch)
             
Index: yum/packageSack.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/yum/packageSack.py,v
retrieving revision 1.23
diff -u -r1.23 packageSack.py
--- yum/packageSack.py	19 Dec 2006 03:43:31 -0000	1.23
+++ yum/packageSack.py	17 Jan 2007 17:43:32 -0000
@@ -18,6 +18,7 @@
 import warnings
 import re
 import fnmatch
+import misc
 
 class PackageSackBase(object):
     """Base class that provides the interface for PackageSacks."""
@@ -317,6 +318,30 @@
     def searchAll(self, arg, query_type):
         return self._computeAggregateListResult("searchAll", arg, query_type)
 
+    def parsePackages(self, pkgspecs):
+        matched = []
+        exactmatch = []
+        unmatched = None
+        for sack in self.sacks.values():
+            if hasattr(sack, "parsePackages"):
+                e, m, u = [], [], []
+                try:
+                    e, m, u = sack.parsePackages(pkgspecs)
+                except PackageSackError:
+                    continue
+
+                exactmatch.extend(e)
+                matched.extend(m)
+                if unmatched is None:
+                    unmatched = set(u)
+                else:
+                    unmatched = unmatched.intersection(set(u))
+
+        matched = misc.unique(matched)
+        exactmatch = misc.unique(exactmatch)
+        unmatched = list(unmatched)
+        return exactmatch, matched, unmatched
+
     def _computeAggregateListResult(self, methodName, *args):
         result = []
         for sack in self.sacks.values():
Index: yum/sqlitesack.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/yum/sqlitesack.py,v
retrieving revision 1.54
diff -u -r1.54 sqlitesack.py
--- yum/sqlitesack.py	15 Dec 2006 14:40:55 -0000	1.54
+++ yum/sqlitesack.py	17 Jan 2007 17:43:33 -0000
@@ -499,6 +499,33 @@
             raise Errors.PackageSackError, 'No Package Matching %s' % name
         return misc.newestInList(allpkg)
 
+    # Do what packages.parsePackages does, but query the DB directly
+    def parsePackages(self, pkgspecs):
+        matched = []
+        exactmatch = []
+        unmatched = list(pkgspecs)
+        for p in pkgspecs:
+            if re.match('[\*\?\[\]]', p):
+                query = PARSE_QUERY % ({ "op": "glob", "q": p })
+                matchres = matched
+            else:
+                query = PARSE_QUERY % ({ "op": "=", "q": p })
+                matchres = exactmatch
+            
+            for (rep, db) in self.primarydb.items():
+                cur = db.cursor()
+                executeSQL(cur, query)
+                res = cur.fetchall()
+                if len(res) > 0:
+                    unmatched.remove(p)
+                    pos = map(lambda x: self.pc(rep,self.db2class(x,True)), res)
+                    matchres.extend(pos)
+
+        exactmatch = misc.unique(exactmatch)
+        matched = misc.unique(matched)
+        unmatched = misc.unique(unmatched)
+        return exactmatch, matched, unmatched
+
     def returnPackages(self, repoid=None):
         """Returns a list of packages, only containing nevra information """
         returnList = []
@@ -506,7 +533,7 @@
             if (repoid == None or repoid == repo.id):
                 cur = cache.cursor()
                 executeSQL(cur, "select pkgId,name,epoch,version,release,arch from packages")
-                for x in cur.fetchall():
+                for x in cur:
                     if (self.excludes[repo].has_key(x['pkgId'])):
                         continue
                     returnList.append(self.pc(repo,self.db2class(x,True)))
@@ -585,3 +612,18 @@
     string2ft = {'f':'file','d': 'dir','g': 'ghost'}
     return [string2ft[x] for x in filetypestring]
 
+
+# Query used by parsePackages
+# op is either '=' or 'like', q is the search term
+# Check against name, nameArch, nameVerRelArch, nameVer, nameVerRel,
+# envra, nevra
+PARSE_QUERY = """
+select pkgId, name, arch, epoch, version, release from packages
+where name %(op)s '%(q)s'
+   or name || '.' || arch %(op)s '%(q)s'
+   or name || '-' || version %(op)s '%(q)s'
+   or name || '-' || version || '-' || release %(op)s '%(q)s'
+   or name || '-' || version || '-' || release || '.' || arch %(op)s '%(q)s'
+   or epoch || ':' || name || '-' || version || '-' || release || '.' || arch %(op)s '%(q)s'
+   or name || '-' || epoch || ':' || version || '-' || release || '.' || arch %(op)s '%(q)s'
+"""
_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel

Reply via email to