diff --git a/yum/misc.py b/yum/misc.py
index 5a59ee4..a587eb6 100644
--- a/yum/misc.py
+++ b/yum/misc.py
@@ -565,6 +565,16 @@ def to_str(obj):
obj = str(obj)
return obj
+def to_xml(item, attrib=False):
+ import xml.sax.saxutils
+ item = to_utf8(item) # verify this does enough conversion
+ item = item.rstrip()
+ if attrib:
+ item = xml.sax.saxutils.escape(item, entities={'"':"""})
+ else:
+ item = xml.sax.saxutils.escape(item)
+ return item
+
def get_my_lang_code():
import locale
mylang = locale.getlocale()
diff --git a/yum/packages.py b/yum/packages.py
index 527b4a5..400962a 100644
--- a/yum/packages.py
+++ b/yum/packages.py
@@ -565,6 +565,12 @@ class YumAvailablePackage(PackageObject, RpmBase):
return self._committime_ret
committime = property(_committime)
+
+ # FIXME test this to see if it causes hell elsewhere
+ def _checksum(self):
+ "Returns the 'default' checksum"
+ return self.checksums[0][1]
+ checksum = property(_checksum)
def getDiscNum(self):
if self.basepath is None:
@@ -730,6 +736,250 @@ class YumAvailablePackage(PackageObject, RpmBase):
csumid = 0
self._checksums.append((ctype, csum, csumid))
+# from here down this is for dumping a package object back out to metadata
+
+
+ def _return_remote_location(self):
+ # break self.remote_url up into smaller pieces
+ base = os.path.dirname(self.remote_url)
+ href = os.path.basename(self.remote_url)
+ msg = """\n""" % (
+ misc.to_xml(base,attrib=True), misc.to_xml(href, attrib=True))
+ return msg
+
+ def _dump_base_items(self):
+
+ packager = url = ''
+ if self.packager:
+ packager = misc.to_xml(self.packager)
+
+ if self.url:
+ url = misc.to_xml(self.url)
+
+ msg = """
+ %s
+ %s
+
+ %s
+ %s
+ %s
+ %s
+ %s
+
+ \n""" % (self.name,
+ self.arch, self.epoch, self.ver, self.rel, self.checksum,
+ misc.to_xml(self.summary), misc.to_xml(self.description), packager,
+ url, self.filetime, self.buildtime, self.packagesize, self.size,
+ self.archivesize)
+
+ msg += self._return_remote_location()
+ return msg
+
+ def _dump_format_items(self):
+ msg = " \n"
+ if self.license:
+ msg += """ %s\n""" % misc.to_xml(self.license)
+ else:
+ msg += """ \n"""
+
+ if self.vendor:
+ msg += """ %s\n""" % misc.to_xml(self.vendor)
+ else:
+ msg += """ \n"""
+
+ if self.group:
+ msg += """ %s\n""" % misc.to_xml(self.group)
+ else:
+ msg += """ \n"""
+
+ if self.buildhost:
+ msg += """ %s\n""" % misc.to_xml(self.buildhost)
+ else:
+ msg += """ \n"""
+
+ if self.sourcerpm:
+ msg += """ %s\n""" % misc.to_xml(self.sourcerpm)
+ msg +=""" """ % (self.hdrstart,
+ self.hdrend)
+ msg += self._dump_pco('provides')
+ msg += self._dump_requires()
+ msg += self._dump_pco('conflicts')
+ msg += self._dump_pco('obsoletes')
+ msg += self._dump_files(True)
+ msg += """\n """
+ return msg
+
+ def _dump_pco(self, pcotype):
+
+ msg = ""
+ mylist = getattr(self, pcotype)
+ if mylist: msg = "\n \n" % pcotype
+ for (name, flags, (e,v,r)) in mylist:
+ pcostring = ''' \n"
+ msg += pcostring
+
+ if mylist: msg += " " % pcotype
+ return msg
+
+ def _return_primary_files(self, list_of_files=None):
+ fileglobs = ['.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$']
+ file_re = []
+ for glob in fileglobs:
+ file_re.append(re.compile(glob))
+
+
+ returns = {}
+ if list_of_files is None:
+ list_of_files = self.returnFileEntries('file')
+ for item in list_of_files:
+ if item is None:
+ continue
+ for glob in file_re:
+ if glob.match(item):
+ returns[item] = 1
+ return returns.keys()
+
+ def _return_primary_dirs(self):
+ dirglobs = ['.*bin\/.*', '^\/etc\/.*']
+ dir_re = []
+
+ for glob in dirglobs:
+ dir_re.append(re.compile(glob))
+
+ returns = {}
+ for item in self.returnFileEntries('dir'):
+ if item is None:
+ continue
+ for glob in dir_re:
+ if glob.match(item):
+ returns[item] = 1
+ return returns.keys()
+
+
+ def _dump_files(self, primary=False):
+ msg =""
+ if not primary:
+ files = self.returnFileEntries('file')
+ dirs = self.returnFileEntries('dir')
+ ghosts = self.returnFileEntries('ghost')
+ else:
+ files = self._return_primary_files()
+ ghosts = self._return_primary_files(list_of_files = self.returnFileEntries('ghost'))
+ dirs = self._return_primary_dirs()
+
+ for fn in files:
+ msg += """ %s\n""" % misc.to_xml(fn)
+ for fn in dirs:
+ msg += """ %s\n""" % misc.to_xml(fn)
+ for fn in ghosts:
+ msg += """ %s\n""" % misc.to_xml(fn)
+
+ return msg
+
+ def _is_pre_req(self, flag):
+ """check the flags for a requirement, return 1 or 0 whether or not requires
+ is a pre-requires or a not"""
+ # FIXME this should probably be put in rpmUtils.miscutils since
+ # - that's what it is
+ newflag = flag
+ if flag is not None:
+ newflag = flag & rpm.RPMSENSE_PREREQ
+ if newflag == rpm.RPMSENSE_PREREQ:
+ return 1
+ else:
+ return 0
+ return 0
+
+ def _requires_with_pre(self): # this should probably be moved into YumHeaderPackage
+ # and a stub put in here
+ """returns requires with pre-require bit"""
+ name = self.hdr[rpm.RPMTAG_REQUIRENAME]
+ lst = self.hdr[rpm.RPMTAG_REQUIREFLAGS]
+ flag = map(flagToString, lst)
+ pre = map(self._is_pre_req, lst)
+ lst = self.hdr[rpm.RPMTAG_REQUIREVERSION]
+ vers = map(stringToVersion, lst)
+ if name is not None:
+ lst = zip(name, flag, vers, pre)
+ mylist = misc.unique(lst)
+ return mylist
+
+ def _dump_requires(self):
+ """returns deps in format"""
+ mylist = self._requires_with_pre()
+
+ msg = ""
+
+ if mylist: msg = "\n \n"
+ for (name, flags, (e,v,r),pre) in mylist:
+ if name.startswith('rpmlib('):
+ continue
+ prcostring = ''' \n"
+ msg += prcostring
+
+ if mylist: msg += " "
+ return msg
+
+ def _dump_changelog(self, clog_limit):
+ if not self.changelog:
+ return ""
+ msg = "\n"
+ clog_count = 0
+ for (ts, author, content) in reversed(sorted(self.changelog)):
+ if clog_limit and clog_count >= clog_limit:
+ break
+ clog_count += 1
+ msg += '''%s\n''' % (
+ misc.to_xml(author, attrib=True), str(ts), misc.to_xml(content))
+ return msg
+
+ def do_primary_xml_dump(self):
+ msg = """\n"""
+ msg += self._dump_base_items()
+ msg += self._dump_format_items()
+ msg += """\n"""
+ return msg
+
+ def do_filelists_xml_dump(self):
+ msg = """\n
+ \n""" % (self.checksum, self.name,
+ self.arch, self.epoch, self.ver, self.rel)
+ msg += self._dump_files()
+ msg += "\n"
+ return msg
+
+ def do_other_xml_dump(self, clog_limit=0):
+ msg = """\n
+ \n""" % (self.checksum, self.name,
+ self.arch, self.epoch, self.ver, self.rel)
+ msg += self._dump_changelog(clog_limit)
+ msg += "\n\n"
+ return msg
+
+
+
class YumHeaderPackage(YumAvailablePackage):
"""Package object built from an rpm header"""
diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py
index 2949df4..15e916b 100644
--- a/yum/sqlitesack.py
+++ b/yum/sqlitesack.py
@@ -242,6 +242,23 @@ class YumAvailablePackageSqlite(YumAvailablePackage, PackageObject, RpmBase):
self.prco[prcotype].append(_share_data(prco_set))
return RpmBase.returnPrco(self, prcotype, printable)
+
+ def _requires_with_pre(self):
+ """returns requires with pre-require bit"""
+ sql = "SELECT name, version, release, epoch, flags,pre " \
+ "FROM requires WHERE pkgKey = ?"
+ cur = self._sql_MD('primary', sql, (self.pkgKey,))
+ requires = []
+ for ob in cur:
+ pre = "0"
+ if ob['pre'].lower() in ['TRUE', 1]:
+ pre = "1"
+ prco_set = (_share_data(ob['name']), _share_data(ob['flags']),
+ (_share_data(ob['epoch']),
+ _share_data(ob['version']),
+ _share_data(ob['release'])), pre)
+ requires.append(prco_set)
+ return requires
class YumSqlitePackageSack(yumRepo.YumPackageSack):
""" Implementation of a PackageSack that uses sqlite cache instead of fully