MINI SHELL

Server : Apache/2.2.2 (Fedora)
System : Linux App1.pathumtani.go.th 2.6.20-1.2320.fc5smp #1 SMP Tue Jun 12 19:40:16 EDT 2007 i686
User : apache ( 48)
PHP Version : 5.2.9
Disable Function : NONE
Directory :  /proc/self/root/proc/self/root/usr/lib/python2.4/site-packages/yum/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //proc/self/root/proc/self/root/usr/lib/python2.4/site-packages/yum/sqlitesack.py
#!/usr/bin/python -tt

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2005 Duke University 

#
# Implementation of the YumPackageSack class that uses an sqlite backend
#

import os
import os.path
import types
import repos
from packages import YumAvailablePackage
from repomd import mdUtils, mdErrors

# Simple subclass of YumAvailablePackage that can load 'simple headers' from
# the database when they are requested
class YumAvailablePackageSqlite(YumAvailablePackage):
    def __init__(self, pkgdict, repoid):
        YumAvailablePackage.__init__(self,pkgdict,repoid)
        self.sack = pkgdict.sack
        self.pkgId = pkgdict.pkgId
        self.simple['id'] = self.pkgId
        self.changelog = None
    
    def loadChangelog(self):
        if hasattr(self, 'dbusedother'):
            return
        self.dbusedother = 1
        self.changelog = self.sack.getChangelog(self.pkgId)

    def returnSimple(self, varname):
        if (not self.simple.has_key(varname) and not hasattr(self,'dbusedsimple')):
            # Make sure we only try once to get the stuff from the database
            self.dbusedsimple = 1
            details = self.sack.getPackageDetails(self.pkgId)
            self.importFromDict(details,self.simple['repoid'])

        return YumAvailablePackage.returnSimple(self,varname)

    def loadFiles(self):
        if (hasattr(self,'dbusedfiles')):
            return
        self.dbusedfiles = 1
        self.files = self.sack.getFiles(self.pkgId)

    def returnChangelog(self):
        self.loadChangelog()
        return YumAvailablePackage.returnChangelog(self)
            
    def returnFileEntries(self, ftype='file'):
        self.loadFiles()
        return YumAvailablePackage.returnFileEntries(self,ftype)
    
    def returnFileTypes(self):
        self.loadFiles()
        return YumAvailablePackage.returnFileTypes(self)

    def returnPrco(self, prcotype):
        if not self.prco[prcotype]:
           self.prco = self.sack.getPrco(self.pkgId, prcotype)
        return self.prco[prcotype]

class YumSqlitePackageSack(repos.YumPackageSack):
    """ Implementation of a PackageSack that uses sqlite cache instead of fully
    expanded metadata objects to provide information """

    def __init__(self, packageClass):
        # Just init as usual and create a dict to hold the databases
        repos.YumPackageSack.__init__(self,packageClass)
        self.primarydb = {}
        self.filelistsdb = {}
        self.otherdb = {}
        self.excludes = {}
        
    def buildIndexes(self):
        # We don't need these
        return

    def _checkIndexes(self, failure='error'):
        return

    # Remove a package
    # Because we don't want to remove a package from the database we just
    # add it to the exclude list
    def delPackage(self, obj):
        repoid = obj.repoid
        self.excludes[repoid][obj.pkgId] = 1

    def addDict(self, repoid, datatype, dataobj, callback=None):
        if (not self.excludes.has_key(repoid)): 
            self.excludes[repoid] = {}
        if datatype == 'metadata':
            if (self.primarydb.has_key(repoid)):
              return
            self.added[repoid] = ['primary']
            self.primarydb[repoid] = dataobj
        elif datatype == 'filelists':
            if (self.filelistsdb.has_key(repoid)):
              return
            self.added[repoid] = ['filelists']
            self.filelistsdb[repoid] = dataobj
        elif datatype == 'otherdata':
            if (self.otherdb.has_key(repoid)):
              return
            self.added[repoid] = ['otherdata']
            self.otherdb[repoid] = dataobj
        else:
            # We can not handle this yet...
            raise "Sorry sqlite does not support %s" % (datatype)
    
    def getChangelog(self,pkgId):
        result = []
        for (rep,cache) in self.otherdb.items():
            cur = cache.cursor()
            cur.execute("select changelog.date as date,\
                changelog.author as author,\
                changelog.changelog as changelog from packages,changelog where packages.pkgId = %s and packages.pkgKey = changelog.pkgKey",pkgId)
            for ob in cur.fetchall():
                result.append(( ob['date'],
                                ob['author'],
                                ob['changelog']
                              ))
        return result

    def getPrco(self,pkgId, prcotype=None):
        if prcotype is not None:
            result = {'requires': [], 'provides': [], 'obsoletes': [], 'conflicts': []}
        else:
            result = { prcotype: [] }
        for (rep, cache) in self.primarydb.items():
            cur = cache.cursor()
            for prco in result.keys():
                cur.execute("select %s.name as name, %s.version as version,\
                    %s.release as release, %s.epoch as epoch, %s.flags as flags\
                    from packages,%s\
                    where packages.pkgId = %s and packages.pkgKey = %s.pkgKey", prco, prco, prco, prco, prco, prco, pkgId, prco)
                for ob in cur.fetchall():
                    name = ob['name']
                    version = ob['version']
                    release = ob['release']
                    epoch = ob['epoch']
                    flags = ob['flags']
                    result[prco].append((name, flags, (epoch, version, release)))
        return result

    # Get all files for a certain pkgId from the filelists.xml metadata
    def getFiles(self,pkgId):
        for (rep,cache) in self.filelistsdb.items():
            found = False
            result = {}
            cur = cache.cursor()
            cur.execute("select filelist.dirname as dirname,\
                filelist.filetypes as filetypes,\
                filelist.filenames as filenames from packages,filelist\
                where packages.pkgId = %s and packages.pkgKey = filelist.pkgKey", pkgId)
            for ob in cur.fetchall():
                found = True
                dirname = ob['dirname']
                filetypes = decodefiletypelist(ob['filetypes'])
                filenames = decodefilenamelist(ob['filenames'])
                while(filenames):
                    if dirname:
                        filename = dirname+'/'+filenames.pop()
                    else:
                        filename = filenames.pop()
                    filetype = filetypes.pop()
                    result.setdefault(filetype,[]).append(filename)
            if (found):
                return result    
        return {}
            
    # Search packages that either provide something containing name
    # or provide a file containing name 
    def searchAll(self, name, query_type='like'):
        
        # This should never be called with a name containing a %
        assert(name.find('%') == -1)
        result = {}
        quotename = name.replace("'","''")
        (dirname,filename) = os.path.split(name)
        
        # check provides
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute("select DISTINCT packages.pkgId as pkgId from provides,packages where provides.name LIKE '%%%s%%' AND provides.pkgKey = packages.pkgKey" % quotename)
            for ob in cur.fetchall():
                if (self.excludes[rep].has_key(ob['pkgId'])):
                    continue

                pkgid = ob['pkgId']
                if not result.has_key(pkgid):
                    pkg = self.getPackageDetails(ob['pkgId'])
                    result[pkgid] = (self.pc(pkg,rep))
        
        # check filelists/dirlists
        for (rep,cache) in self.filelistsdb.items():
            querystrings = []
            # dirnames
            # just the dirname
            if dirname != '':
                tmp = "select packages.pkgId as pkgId,\
                filelist.dirname as dirname,\
                filelist.filetypes as filetypes,\
                filelist.filenames as filenames \
                from packages,filelist where \
                filelist.dirname LIKE '%%%s%%' \
                AND (filelist.pkgKey = packages.pkgKey)" % (dirname)
                querystrings.append(tmp)
                
            # look at full quotename
            tmp = "select packages.pkgId as pkgId,\
                filelist.dirname as dirname,\
                filelist.filetypes as filetypes,\
                filelist.filenames as filenames \
                from packages,filelist where \
                filelist.dirname LIKE '%%%s%%' \
                AND (filelist.pkgKey = packages.pkgKey)" % (quotename)
            querystrings.append(tmp)

            # filenames
            tmp = "select packages.pkgId as pkgId,\
                filelist.dirname as dirname,\
                filelist.filetypes as filetypes,\
                filelist.filenames as filenames \
                from packages,filelist where \
                filelist.filenames LIKE '%%%s%%'\
                AND (filelist.pkgKey = packages.pkgKey)" % (filename)
            
            querystrings.append(tmp)
        
            for querystring in querystrings:
                cur = cache.cursor()
                cur.execute("%s" % querystring)

                # cull the results for false positives
                for ob in cur.fetchall():
                    # Check if it is an actual match
                    # The query above can give false positives, when
                    # a package provides /foo/aaabar it will also match /foo/bar
                    if (self.excludes[rep].has_key(ob['pkgId'])):
                        continue
                    real = False
        
                    for filename in decodefilenamelist(ob['filenames']):
                        if (ob['dirname'] + '/' + filename).find(name) != -1:
                            real = True
                    if (not real):
                        continue

                    pkgid = ob['pkgId']
                    if not result.has_key(pkgid):
                        pkg = self.getPackageDetails(ob['pkgId'])
                        result[pkgid] = (self.pc(pkg,rep))

        return result.values()
    
    def returnObsoletes(self):
        obsoletes = {}
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute("select packages.name as name,\
                packages.pkgId as pkgId,\
                packages.arch as arch, packages.epoch as epoch,\
                packages.release as release, packages.version as version,\
                obsoletes.name as oname, obsoletes.epoch as oepoch,\
                obsoletes.release as orelease, obsoletes.version as oversion,\
                obsoletes.flags as oflags\
                from obsoletes,packages where obsoletes.pkgKey = packages.pkgKey")
            for ob in cur.fetchall():
                # If the package that is causing the obsoletes is excluded
                # continue without processing the obsoletes
                if (self.excludes[rep].has_key(ob['pkgId'])):
                    continue
                key = ( ob['name'],ob['arch'],
                        ob['epoch'],ob['version'],
                        ob['release'])
                (n,f,e,v,r) = ( ob['oname'],ob['oflags'],
                                ob['oepoch'],ob['oversion'],
                                ob['orelease'])

                obsoletes.setdefault(key,[]).append((n,f,(e,v,r)))

        return obsoletes

    def getPackageDetails(self,pkgId):
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute("select * from packages where pkgId = %s",pkgId)
            for ob in cur.fetchall():
                pkg = self.db2class(ob)
                return pkg

    def searchPrco(self, name, prcotype):
        """return list of packages having prcotype name (any evr and flag)"""
        results = []
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute("select * from %s where name = %s" , (prcotype, name))
            prcos = cur.fetchall()
            for res in prcos:
                cur.execute("select * from packages where pkgKey = %s" , (res['pkgKey']))
                for x in cur.fetchall():
                    pkg = self.db2class(x)
                    if (self.excludes[rep].has_key(pkg.pkgId)):
                        continue
                                            
                    # Add this provides to prco otherwise yum doesn't understand
                    # that it matches
                    pkg.prco = {prcotype: 
                      [
                      { 'name': res.name,
                        'flags': res.flags,
                        'rel': res.release,
                        'ver': res.version,
                        'epoch': res.epoch
                      }
                      ]
                    }
                    results.append(self.pc(pkg,rep))


        # If it's not a provides or a filename, we are done
        if (prcotype != "provides" or name.find('/') != 0):
            return results

        # If it is a filename, search the primary.xml file info
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute("select * from files where name = %s" , (name))
            files = cur.fetchall()
            for res in files:
                cur.execute("select * from packages where pkgKey = %s" , (res['pkgKey']))
                for x in cur.fetchall():
                    pkg = self.db2class(x)
                    if (self.excludes[rep].has_key(pkg.pkgId)):
                        continue
                                            
                    pkg.files = {name: res['type']}
                    results.append(self.pc(pkg,rep))

        # If it is a filename, search the files.xml file info
        for (rep,cache) in self.filelistsdb.items():
            cur = cache.cursor()
            (dirname,filename) = os.path.split(name)
            cur.execute("select packages.pkgId as pkgId,\
                filelist.dirname as dirname,\
                filelist.filetypes as filetypes,\
                filelist.filenames as filenames \
                from filelist,packages where dirname = %s AND filelist.pkgKey = packages.pkgKey" , (dirname))
            files = cur.fetchall()
            for res in files:
                if (self.excludes[rep].has_key(res['pkgId'])):
                    continue
                                        
                # If it matches the dirname, that doesnt mean it matches
                # the filename, check if it does
                if filename and \
                  not filename in res['filenames'].split('/'):
                    continue
                # If it matches we only know the packageId
                pkg = self.getPackageDetails(res['pkgId'])
                results.append(self.pc(pkg,rep))
        return results

    def searchProvides(self, name):
        """return list of packages providing name (any evr and flag)"""
        return self.searchPrco(name, "provides")
                
    def searchRequires(self, name):
        """return list of packages requiring name (any evr and flag)"""
        return self.searchPrco(name, "requires")

    def searchObsoletes(self, name):
        """return list of packages obsoleting name (any evr and flag)"""
        return self.searchPrco(name, "obsoletes")

    def searchConflicts(self, name):
        """return list of packages conflicting with name (any evr and flag)"""
        return self.searchPrco(name, "conflicts")

    # TODO this seems a bit ugly and hackish
    def db2class(self,db,nevra_only=False):
      class tmpObject:
        pass
      y = tmpObject()
      y.nevra = (db.name,db.epoch,db.version,db.release,db.arch)
      y.sack = self
      y.pkgId = db.pkgId
      if (nevra_only):
        return y
      y.hdrange = {'start': db.rpm_header_start,'end': db.rpm_header_end}
      y.location = {'href': db.location_href,'value': '', 'base': db.location_base}
      y.checksum = {'pkgid': 'YES','type': db.checksum_type, 
                    'value': db.checksum_value }
      y.time = {'build': db.time_build, 'file': db.time_file }
      y.size = {'package': db.size_package, 'archive': db.size_archive, 'installed': db.size_installed }
      y.info = {'summary': db.summary, 'description': db['description'],
                'packager': db.rpm_packager, 'group': db.rpm_group,
                'buildhost': db.rpm_buildhost, 'sourcerpm': db.rpm_sourcerpm,
                'url': db.url, 'vendor': db.rpm_vendor, 'license': db.rpm_license }
      return y

    def simplePkgList(self, repoid=None):
        """returns a list of pkg tuples (n, a, e, v, r) optionally from a single repoid"""
        simplelist = []
        for (rep,cache) in self.primarydb.items():
            if (repoid == None or repoid == rep):
                cur = cache.cursor()
                cur.execute("select pkgId,name,epoch,version,release,arch from packages")
                for pkg in cur.fetchall():
                    if (self.excludes[rep].has_key(pkg.pkgId)):
                        continue                        
                    simplelist.append((pkg.name, pkg.arch, pkg.epoch, pkg.version, pkg.release)) 
                    
        return simplelist

    def returnNewestByNameArch(self, naTup=None):
        # If naTup is set do it from the database otherwise use our parent's
        # returnNewestByNameArch
        if (not naTup):
            # TODO process excludes here
            return repos.YumPackageSack.returnNewestByNameArch(self, naTup)

        # First find all packages that fulfill naTup
        allpkg = []
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute("select pkgId,name,epoch,version,release,arch from packages where name=%s and arch=%s",naTup)
            for x in cur.fetchall():
                if (self.excludes[rep].has_key(x.pkgId)):
                    continue                    
                allpkg.append(self.pc(self.db2class(x,True),rep))
        
        # if we've got zilch then raise
        if not allpkg:
            raise mdErrors.PackageSackError, 'No Package Matching %s.%s' % naTup
        return mdUtils.newestInList(allpkg)

    def returnNewestByName(self, name=None):
        # If name is set do it from the database otherwise use our parent's
        # returnNewestByName
        if (not name):
            return repos.YumPackageSack.returnNewestByName(self, name)

        # First find all packages that fulfill name
        allpkg = []
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute("select pkgId,name,epoch,version,release,arch from packages where name=%s", name)
            for x in cur.fetchall():
                if (self.excludes[rep].has_key(x.pkgId)):
                    continue                    
                allpkg.append(self.pc(self.db2class(x,True),rep))
        
        # if we've got zilch then raise
        if not allpkg:
            raise mdErrors.PackageSackError, 'No Package Matching %s' % name
        return mdUtils.newestInList(allpkg)

    def returnPackages(self, repoid=None):
        """Returns a list of packages, only containing nevra information """
        returnList = []
        for (rep,cache) in self.primarydb.items():
            if (repoid == None or repoid == rep):
                cur = cache.cursor()
                cur.execute("select pkgId,name,epoch,version,release,arch from packages")
                for x in cur.fetchall():
                    if (self.excludes[rep].has_key(x.pkgId)):
                        continue                    
                    returnList.append(self.pc(self.db2class(x,True),rep))
        return returnList

    def searchNevra(self, name=None, epoch=None, ver=None, rel=None, arch=None):        
        """return list of pkgobjects matching the nevra requested"""
        returnList = []
        
        # make sure some dumbass didn't pass us NOTHING to search on
        empty = True
        for arg in (name, epoch, ver, rel, arch):
            if arg:
                empty = False
        if empty:
            return returnList
        
        # make up our execute string
        q = "select * from packages WHERE"
        for (col, var) in [('name', name), ('epoch', epoch), ('version', ver),
                           ('arch', arch), ('release', rel)]:
            if var:
                if q[-5:] != 'WHERE':
                    q = q + ' AND %s = "%s"' % (col, var)
                else:
                    q = q + ' %s = "%s"' % (col, var)
            
        # Search all repositories            
        for (rep,cache) in self.primarydb.items():
            cur = cache.cursor()
            #cur.execute("select * from packages WHERE name = %s AND epoch = %s AND version = %s AND release = %s AND arch = %s" , (name,epoch,ver,rel,arch))
            cur.execute(q)
            for x in cur.fetchall():
                if (self.excludes[rep].has_key(x.pkgId)):
                    continue
                returnList.append(self.pc(self.db2class(x),rep))
        return returnList
    
    def excludeArchs(self, archlist):
        """excludes incompatible arches - archlist is a list of compat arches"""
        tmpstring = "select * from packages WHERE "
        for arch in archlist:
            tmpstring = tmpstring + 'arch != "%s" AND ' % arch
        
        last = tmpstring.rfind('AND') # clip that last AND
        querystring = tmpstring[:last]
        for (rep, cache) in self.primarydb.items():
            cur = cache.cursor()
            cur.execute(querystring)
            for x in cur.fetchall():
                obj = self.pc(self.db2class(x), rep)
                self.delPackage(obj)

# Simple helper functions

# Return a string representing filenamelist (filenames can not contain /)
def encodefilenamelist(filenamelist):
    return '/'.join(filenamelist)

# Return a list representing filestring (filenames can not contain /)
def decodefilenamelist(filenamestring):
    return filenamestring.split('/')

# Return a string representing filetypeslist
# filetypes should be file, dir or ghost
def encodefiletypelist(filetypelist):
    result = ''
    ft2string = {'file': 'f','dir': 'd','ghost': 'g'}
    for x in filetypelist:
        result += ft2string[x]
    return result

# Return a list representing filetypestring
# filetypes should be file, dir or ghost
def decodefiletypelist(filetypestring):
    string2ft = {'f':'file','d': 'dir','g': 'ghost'}
    return [string2ft[x] for x in filetypestring]


Anon7 - 2021