diff --git a/yum/constants.py b/yum/constants.py index 23e7f27..f0a8d04 100644 --- a/yum/constants.py +++ b/yum/constants.py @@ -97,3 +97,4 @@ RPM_TO_SQLITE = { 'packagesize' : 'size_package', 'vendor' : 'rpm_vendor', 'license' : 'rpm_license' } + diff --git a/yum/packages.py b/yum/packages.py index 4cf42ad..c91acf3 100644 --- a/yum/packages.py +++ b/yum/packages.py @@ -816,11 +816,48 @@ class YumHeaderPackage(YumAvailablePackage): class YumInstalledPackage(YumHeaderPackage): """super class for dealing with packages in the rpmdb""" - def __init__(self, hdr): - fakerepo = FakeRepository('installed') + def __init__(self, hdr, additional_obj=None): + repo = None + po = misc.GenericHolder() # not a REAL Po of any kind + if additional_obj: + # this is hacky + po.name = hdr['name'] + po.ver = hdr['version'] + po.arch = hdr['arch'] + po.rel = hdr['release'] + po.pkgid = hdr[rpm.RPMTAG_SHA1HEADER] + repoid = additional_obj.get(po, 'repoid') + + if repoid: + fakerepo = FakeRepository(repoid) + else: + fakerepo = FakeRepository('installed') + del po + + self.additional_data = additional_obj fakerepo.cost = 0 YumHeaderPackage.__init__(self, fakerepo, hdr) + + def __getattr__(self, thing): + + if thing in self.hdr.keys(): + return self.hdr[thing] + + if self.additional_data: + data = self.additional_data.get(self, thing) + if data: + return data + + raise AttributeError, thing + + def set_additional(self, attr, value): + return self.additional_data.add(self, attr, value) + + def del_additional(self, attr): + return self.additional_data.delete(self, attr) + + class YumLocalPackage(YumHeaderPackage): """Class to handle an arbitrary package from a file path this inherits most things from YumInstalledPackage because diff --git a/yum/rpmsack.py b/yum/rpmsack.py index c715764..196bb51 100644 --- a/yum/rpmsack.py +++ b/yum/rpmsack.py @@ -14,8 +14,11 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import rpm +import glob import types import warnings +import os +import os.path from rpmUtils import miscutils from rpmUtils.transaction import initReadOnlyTransaction @@ -57,6 +60,8 @@ class RPMDBPackageSack(PackageSackBase): 'conflicts' : { }, 'obsoletes' : { }, } + self.additional_data = RPMDBAdditionalData() + def _get_pkglist(self): '''Getter for the pkglist property. @@ -299,7 +304,7 @@ class RPMDBPackageSack(PackageSackBase): def _makePackageObject(self, hdr, index): if self._idx2pkg.has_key(index): return self._idx2pkg[index] - po = YumInstalledPackage(hdr) + po = YumInstalledPackage(hdr, additional_obj=self.additional_data) po.idx = index self._idx2pkg[index] = po return po @@ -459,6 +464,117 @@ class RPMDBPackageSack(PackageSackBase): def whatRequires(self, name, flags, version): # XXX deprecate? return [po.pkgtup for po in self.getRequires(name, flags, version)] + +class RPMDBAdditionalData(object): + """class for access to the additional data not able to be stored in the + rpmdb""" + # dir: /var/lib/yum/yumdb/ + # pkgs stored in name[0]/name[1]/pkgid-name-ver-rel-arch dirs + # dirs have files per piece of info we're keeping + # repoid, install reason, status, blah, (group installed for?), notes? + + def __init__(self, db_path='/var/lib/yum/yumdb'): + self.db_path = db_path + self.writable = False + self._packages = {} # pkgid = dir + if not os.path.exists(self.db_path): + try: + os.makedirs(self.db_path) + except (IOError, OSError), e: + # some sort of useful thing here? A warning? + return + else: + if os.access(self.db_path, os.W_OK): + self.writable = True + + # glob the path and get a dict of pkgs to their subdir + glb = '%s/*/*/' % self.db_path + pkgdirs = glob.glob(glb) + for d in pkgdirs: + pkgid = os.path.basename(d).split('-')[0] + self._packages[pkgid] = d + + def _write(self, base, attr, value): + + if not os.path.exists(base): + os.makedirs(base) + + fn = base + '/' + attr + fn = os.path.normpath(fn) + fo = open(fn, 'w') + try: + fo.write(value) + except (OSError, IOError), e: + return False + + fo.close() + del fo + del fn + return True + + + + def _read(self, base, attr): + """returns none if file not present""" + fn = base + '/' + attr + if not os.path.exists(fn): + return None + + fo = open(fn, 'r') + res = fo.read() + fo.close() + del fo + del fn + return res + + def _get_dir_name(self, po): + if po.pkgid in self._packages: + return self._packages[po.pkgid] + return '%s/%s/%s/%s-%s-%s-%s-%s' % (self.db_path, po.name[0], + po.name[1], po.pkgid, po.name, po.ver, + po.rel, po.arch) + + def add(self, po, attr, value): + """add the value to this attribute to the additional db""" + if not self.writable: + # maybe a nice warning? + return False + + mydir = self._get_dir_name(po) + + if self._write(mydir, attr, value): + self._packages[po.pkgid] = mydir + return True + + return False + + def get(self, po, attr, default=None): + """retrieve an add'l data obj""" + mydir = self._get_dir_name(po) + res = self._read(mydir, attr) + if not res: + return default + return res + + def delete(self, po, attr): + """remove the attribute file""" + if not self.writable: + return False + + mydir = self._get_dir_name(po) + fn = mydir + '/' + attr + if os.path.exists(fn): + try: + os.unlink(fn) + except (IOError, OSError): + return False + return True + + def sync_with_rpmdb(self, rpmdbobj): + pass + + + def main(): sack = RPMDBPackageSack('/')