[Yum-devel] [PATCH 3/3] pkgtags db - searching

Seth Vidal skvidal at fedoraproject.org
Fri Feb 5 22:42:04 UTC 2010


this patch adds the pkgtags metatadata and the integrates it into our
search mechanism. Completely optional repodata format.

Also adds a decompress() function from yum.misc that allows for us
to pass files to it and not care what compression mechanism they are using
it's a bit simplistic at the moment but can easily be enhanced.
---
 yum/__init__.py |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 yum/misc.py     |   25 +++++++++++++++++++
 yum/repos.py    |    2 +-
 3 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/yum/__init__.py b/yum/__init__.py
index 083b445..8b69788 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -44,6 +44,7 @@ import rpmUtils.updates
 from rpmUtils.arch import canCoinstall, ArchStorage, isMultiLibArch
 import rpmUtils.transaction
 import comps
+import pkgtag_db
 from repos import RepoStorage
 import misc
 from parser import ConfigPreProcessor, varReplace
@@ -144,6 +145,7 @@ class YumBase(depsolve.Depsolve):
         self._history = None
         self._pkgSack = None
         self._lockfile = None
+        self._tags = None
         self.skipped_packages = []   # packages skip by the skip-broken code
         self.logger = logging.getLogger("yum.YumBase")
         self.verbose_logger = logging.getLogger("yum.verbose.YumBase")
@@ -719,6 +721,38 @@ class YumBase(depsolve.Depsolve):
         self.verbose_logger.debug('group time: %0.3f' % (time.time() - group_st))                
         return self._comps
 
+    def _getTags(self):
+        """ create the tags object used to search/report from the pkgtags 
+            metadata"""
+        
+        tag_st = time.time()
+        self.verbose_logger.log(logginglevels.DEBUG_4,
+                                _('Getting pkgtags metadata'))
+        
+        if self._tags is None:
+            self._tags = yum.pkgtag_db.PackageTags()
+           
+            for repo in self.repos.listEnabled():
+                if 'pkgtags' not in repo.repoXML.fileTypes():
+                    continue
+
+                self.verbose_logger.log(logginglevels.DEBUG_4,
+                    _('Adding tags from repository: %s'), repo)
+                
+                # fetch the sqlite tagdb
+                try:
+                    tag_md = repo.retrieveMD('pkgtags')
+                    tag_sqlite  = yum.misc.decompress(tag_md)
+                    # feed it into _tags.add()
+                    self._tags.add(repo.id, tag_sqlite)
+                except (Errors.RepoError, Errors.PkgTagsError), e:
+                    msg = _('Failed to add Pkg Tags for repository: %s - %s') % (repo, str(e))
+                    self.logger.critical(msg)
+                    
+                
+        self.verbose_logger.debug('tags time: %0.3f' % (time.time() - tag_st))
+        return self._tags
+        
     def _getHistory(self):
         """auto create the history object that to access/append the transaction
            history information. """
@@ -764,6 +798,11 @@ class YumBase(depsolve.Depsolve):
                        fset=lambda self, value: setattr(self, "_history",value),
                        fdel=lambda self: setattr(self, "_history", None),
                        doc="Yum History Object")
+
+    pkgtags = property(fget=lambda self: self._getTags(),
+                       fset=lambda self, value: setattr(self, "_tags",value),
+                       fdel=lambda self: setattr(self, "_tags", None),
+                       doc="Yum Package Tags Object")
     
     
     def doSackFilelistPopulate(self):
@@ -2076,6 +2115,22 @@ class YumBase(depsolve.Depsolve):
         results2sorted_lists(tmpres, sorted_lists)
         del tmpres
 
+        tmpres = self.searchPackageTags(real_crit_lower)
+        for pkg in tmpres:
+            count = 0
+            matchkeys = []
+            tagresults = []
+            for (match, taglist) in tmpres[pkg]:
+                count += len(taglist)
+                matchkeys.append(rcl2c[match])
+                tagresults.extend(taglist)
+
+
+            if count not in sorted_lists: sorted_lists[count] = []
+            sorted_lists[count].append((pkg, matchkeys, tagresults))
+        
+        del tmpres
+        
         # By default just sort using package sorting
         sort_func = operator.itemgetter(0)
         if keys:
@@ -2097,7 +2152,22 @@ class YumBase(depsolve.Depsolve):
                 if not showdups:
                     yielded[(po.name, po.arch)] = 1
 
-
+    def searchPackageTags(self, criteria):
+        results = {} # name = [(criteria, taglist)]
+        for c in criteria:
+            c = c.lower()
+            res = self.pkgtags.search_tags(c)
+            for (name, taglist) in res.items():
+                pkgs = self.pkgSack.searchNevra(name=name)
+                if not pkgs:
+                    continue
+                pkg = pkgs[0]
+                if pkg not in results:
+                    results[pkg] = []
+                results[pkg].append((c, taglist))
+        
+        return results
+        
     def searchPackages(self, fields, criteria, callback=None):
         """Search specified fields for matches to criteria
            optional callback specified to print out results
diff --git a/yum/misc.py b/yum/misc.py
index 4b0226b..d63993b 100644
--- a/yum/misc.py
+++ b/yum/misc.py
@@ -17,6 +17,7 @@ import glob
 import pwd
 import fnmatch
 import bz2
+import gzip
 from stat import *
 try:
     import gpgme
@@ -945,3 +946,27 @@ def get_uuid(savepath):
         
         return myid
         
+def decompress(filename):
+    """take a filename and decompress it into the same relative location.
+       if the file is not compressed just return the file"""
+    out = filename
+    if filename.endswith('.gz'):
+        out = filename.replace('.gz', '')
+        decom = gzip.open(filename)
+        fo = open(out, 'w')
+        fo.write(decom.read())
+        fo.flush()
+        fo.close()
+        decom.close() 
+    elif filename.endswith('.bz') or filename.endswith('.bz2'):
+        if filename.endswith('.bz'):
+            out = filename.replace('.bz','')
+        else:
+            out = filename.replace('.bz2', '')
+        bunzipFile(filename, out)
+
+    #add magical lzma/xz trick here
+    
+    return out
+    
+    
diff --git a/yum/repos.py b/yum/repos.py
index c6ebf8f..cd477ba 100644
--- a/yum/repos.py
+++ b/yum/repos.py
@@ -206,7 +206,7 @@ class RepoStorage:
     def setCacheDir(self, cachedir):
         """sets the cachedir value in all repos"""
         
-        self.repos._cachedir = cachedir
+        self._cachedir = cachedir
         for repo in self.repos.values():
             repo.old_base_cache_dir = repo.basecachedir
             repo.basecachedir = cachedir
-- 
1.6.6



More information about the Yum-devel mailing list