[createrepo/f16] f16 createrepo 0.9.9
Seth Vidal
skvidal at fedoraproject.org
Fri Jul 29 19:56:44 UTC 2011
commit 2334c203595731250e0df2d62adab96f333a8cdb
Author: Seth Vidal <skvidal at fedoraproject.org>
Date: Fri Jul 29 15:56:31 2011 -0400
f16 createrepo 0.9.9
createrepo-head.patch | 419 +++++++++++++++++++++++++++++++++++++++++++++++--
createrepo.spec | 6 +-
2 files changed, 413 insertions(+), 12 deletions(-)
---
diff --git a/createrepo-head.patch b/createrepo-head.patch
index 5203f35..14e40e6 100644
--- a/createrepo-head.patch
+++ b/createrepo-head.patch
@@ -1,5 +1,31 @@
+diff --git a/createrepo.bash b/createrepo.bash
+index 54ac8b2..4222fa0 100644
+--- a/createrepo.bash
++++ b/createrepo.bash
+@@ -30,6 +30,10 @@ _cr_createrepo()
+ COMPREPLY=( $( compgen -f -o plusdirs -X '!*.rpm' -- "$2" ) )
+ return 0
+ ;;
++ --retain-old-md)
++ COMPREPLY=( $( compgen -W '0 1 2 3 4 5 6 7 8 9' -- "$2" ) )
++ return 0
++ ;;
+ --num-deltas)
+ COMPREPLY=( $( compgen -W '1 2 3 4 5 6 7 8 9' -- "$2" ) )
+ return 0
+@@ -42,8 +46,8 @@ _cr_createrepo()
+ --cachedir --checkts --no-database --update --update-md-path
+ --skip-stat --split --pkglist --includepkg --outputdir
+ --skip-symlinks --changelog-limit --unique-md-filenames
+- --simple-md-filenames --distro --content --repo --revision --deltas
+- --oldpackagedirs --num-deltas --read-pkgs-list
++ --simple-md-filenames --retain-old-md --distro --content --repo
++ --revision --deltas --oldpackagedirs --num-deltas --read-pkgs-list
+ --max-delta-rpm-size --workers' -- "$2" ) )
+ else
+ COMPREPLY=( $( compgen -d -- "$2" ) )
diff --git a/createrepo/__init__.py b/createrepo/__init__.py
-index 8f2538e..8549188 100644
+index 8f2538e..30f7422 100644
--- a/createrepo/__init__.py
+++ b/createrepo/__init__.py
@@ -27,11 +27,11 @@ import stat
@@ -17,7 +43,15 @@ index 8f2538e..8549188 100644
import rpmUtils.transaction
from utils import _, errorprint, MDError
-@@ -530,39 +530,19 @@ class MetaDataGenerator:
+@@ -110,6 +110,7 @@ class MetaDataConfig(object):
+ self.worker_cmd = '/usr/share/createrepo/worker.py'
+
+ #self.worker_cmd = './worker.py' # helpful when testing
++ self.retain_old_md = 0
+
+ class SimpleMDCallBack(object):
+ def errorlog(self, thing):
+@@ -530,39 +531,19 @@ class MetaDataGenerator:
old_pkg = pkg
if pkg.find("://") != -1:
old_pkg = os.path.basename(pkg)
@@ -67,7 +101,7 @@ index 8f2538e..8549188 100644
#FIXME - if we're in update and we have deltas enabled
# check the presto data for this pkg and write its info back out
# to our deltafile
-@@ -584,12 +564,12 @@ class MetaDataGenerator:
+@@ -584,12 +565,12 @@ class MetaDataGenerator:
po = None
if isinstance(pkg, YumAvailablePackage):
po = pkg
@@ -82,7 +116,7 @@ index 8f2538e..8549188 100644
self.read_pkgs.append(pkg)
if po:
-@@ -609,7 +589,7 @@ class MetaDataGenerator:
+@@ -609,7 +590,7 @@ class MetaDataGenerator:
# open the files they created and write them out to our metadata
# add up the total pkg counts and return that value
worker_tmp_path = tempfile.mkdtemp()
@@ -91,7 +125,7 @@ index 8f2538e..8549188 100644
worker_cmd_dict = {}
worker_jobs = {}
base_worker_cmdline = [self.conf.worker_cmd,
-@@ -617,7 +597,8 @@ class MetaDataGenerator:
+@@ -617,7 +598,8 @@ class MetaDataGenerator:
'--pkgoptions=_collapse_libc_requires=%s' % self.conf.collapse_glibc_requires,
'--pkgoptions=_cachedir=%s' % self.conf.cachedir,
'--pkgoptions=_baseurl=%s' % self.conf.baseurl,
@@ -101,7 +135,7 @@ index 8f2538e..8549188 100644
if self.conf.quiet:
base_worker_cmdline.append('--quiet')
-@@ -660,7 +641,12 @@ class MetaDataGenerator:
+@@ -660,7 +642,12 @@ class MetaDataGenerator:
if line:
self.callback.errorlog('Worker %s: %s' % (num, line.rstrip()))
@@ -115,7 +149,7 @@ index 8f2538e..8549188 100644
if not self.conf.quiet:
self.callback.log("Workers Finished")
# finished with workers
-@@ -784,7 +770,6 @@ class MetaDataGenerator:
+@@ -784,7 +771,6 @@ class MetaDataGenerator:
return self._old_package_dict
self._old_package_dict = {}
@@ -123,7 +157,7 @@ index 8f2538e..8549188 100644
for d in self.conf.oldpackage_paths:
for f in self.getFileList(d, '.rpm'):
fp = d + '/' + f
-@@ -874,7 +859,6 @@ class MetaDataGenerator:
+@@ -874,7 +860,6 @@ class MetaDataGenerator:
thisdata = RepoData()
thisdata.type = mdtype
@@ -131,7 +165,7 @@ index 8f2538e..8549188 100644
thisdata.location = (self.conf.baseurl, os.path.join(self.conf.finaldir, sfile))
thisdata.checksum = (self.conf.sumtype, csum)
if compress:
-@@ -1046,7 +1030,7 @@ class MetaDataGenerator:
+@@ -1046,7 +1031,7 @@ class MetaDataGenerator:
if self.conf.additional_metadata:
@@ -140,7 +174,7 @@ index 8f2538e..8549188 100644
mdcontent = self._createRepoDataObject(md_file, md_type)
repomd.repoData[mdcontent.type] = mdcontent
-@@ -1110,12 +1094,6 @@ class MetaDataGenerator:
+@@ -1110,23 +1095,42 @@ class MetaDataGenerator:
raise MDError, _(
'Could not remove old metadata file: %s: %s') % (oldfile, e)
@@ -150,10 +184,93 @@ index 8f2538e..8549188 100644
- except (OSError, IOError), e:
- old_contents = []
-
++ old_to_remove = []
++ old_pr = []
++ old_fl = []
++ old_ot = []
++ old_pr_db = []
++ old_fl_db = []
++ old_ot_db = []
for f in os.listdir(output_old_dir):
oldfile = os.path.join(output_old_dir, f)
finalfile = os.path.join(output_final_dir, f)
-@@ -1240,7 +1218,6 @@ class SplitMetaDataGenerator(MetaDataGenerator):
+- if f.find('-') != -1 and f.split('-')[1] in ('primary.sqlite.bz2',
+- 'filelists.sqlite.bz2', 'primary.xml.gz','other.sqlite.bz2',
+- 'other.xml.gz','filelists.xml.gz'):
+- os.remove(oldfile) # kill off the old ones
+- continue
++
++ for (end,lst) in (('-primary.sqlite.bz2', old_pr_db), ('-primary.xml.gz', old_pr),
++ ('-filelists.sqlite.bz2', old_fl_db), ('-filelists.xml.gz', old_fl),
++ ('-other.sqlite.bz2', old_ot_db), ('-other.xml.gz', old_ot)):
++ if f.endswith(end):
++ lst.append(oldfile)
++ break
++
++ # make a list of the old metadata files we don't want to remove.
++ for lst in (old_pr, old_fl, old_ot, old_pr_db, old_fl_db, old_ot_db):
++ sortlst = sorted(lst, key=lambda x: os.path.getmtime(x),
++ reverse=True)
++ for thisf in sortlst[self.conf.retain_old_md:]:
++ old_to_remove.append(thisf)
++
++ for f in os.listdir(output_old_dir):
++ oldfile = os.path.join(output_old_dir, f)
++ finalfile = os.path.join(output_final_dir, f)
++
+ if f in ('filelists.sqlite.bz2', 'other.sqlite.bz2',
+- 'primary.sqlite.bz2'):
+- os.remove(oldfile)
++ 'primary.sqlite.bz2') or oldfile in old_to_remove:
++ try:
++ os.remove(oldfile)
++ except (OSError, IOError), e:
++ raise MDError, _(
++ 'Could not remove old metadata file: %s: %s') % (oldfile, e)
+ continue
+
+ if os.path.exists(finalfile):
+@@ -1147,14 +1151,11 @@ class MetaDataGenerator:
+ msg += _('Error was %s') % e
+ raise MDError, msg
+
+- try:
+- os.rmdir(output_old_dir)
+- except OSError, e:
+- self.errorlog(_('Could not remove old metadata dir: %s')
+- % self.conf.olddir)
+- self.errorlog(_('Error was %s') % e)
+- self.errorlog(_('Please clean up this directory manually.'))
++ self._cleanup_tmp_repodata_dir()
++ self._write_out_read_pkgs_list()
++
+
++ def _write_out_read_pkgs_list(self):
+ # write out the read_pkgs_list file with self.read_pkgs
+ if self.conf.read_pkgs_list:
+ try:
+@@ -1167,6 +1168,20 @@ class MetaDataGenerator:
+ % self.conf.read_pkgs_list)
+ self.errorlog(_('Error was %s') % e)
+
++ def _cleanup_tmp_repodata_dir(self):
++ output_old_dir = os.path.join(self.conf.outputdir, self.conf.olddir)
++ output_temp_dir = os.path.join(self.conf.outputdir, self.conf.tempdir)
++ for dirbase in (self.conf.olddir, self.conf.tempdir):
++ dirpath = os.path.join(self.conf.outputdir, dirbase)
++ if os.path.exists(dirpath):
++ try:
++ os.rmdir(dirpath)
++ except OSError, e:
++ self.errorlog(_('Could not remove temp metadata dir: %s')
++ % dirbase)
++ self.errorlog(_('Error was %s') % e)
++ self.errorlog(_('Please clean up this directory manually.'))
++
+ def setup_sqlite_dbs(self, initdb=True):
+ """sets up the sqlite dbs w/table schemas and db_infos"""
+ destdir = os.path.join(self.conf.outputdir, self.conf.tempdir)
+@@ -1240,7 +1255,6 @@ class SplitMetaDataGenerator(MetaDataGenerator):
self.conf.baseurl = self._getFragmentUrl(self.conf.baseurl, mediano)
try:
self.openMetadataDocs()
@@ -161,6 +278,61 @@ index 8f2538e..8549188 100644
for mydir in self.conf.directories:
self.conf.baseurl = self._getFragmentUrl(self.conf.baseurl, mediano)
self.writeMetadataDocs(filematrix[mydir], mydir)
+diff --git a/createrepo/merge.py b/createrepo/merge.py
+index b3b2ea1..1ac43bb 100644
+--- a/createrepo/merge.py
++++ b/createrepo/merge.py
+@@ -24,6 +24,7 @@ from yum.misc import unique, getCacheDir
+ import yum.update_md
+ import rpmUtils.arch
+ import operator
++from utils import MDError
+ import createrepo
+ import tempfile
+
+@@ -84,6 +85,8 @@ class RepoMergeBase:
+ # in the repolist
+ count = 0
+ for r in self.repolist:
++ if r[0] == '/':
++ r = 'file://' + r # just fix the file repos, this is silly.
+ count +=1
+ rid = 'repo%s' % count
+ n = self.yumbase.add_enable_repo(rid, baseurls=[r],
+@@ -92,7 +95,10 @@ class RepoMergeBase:
+ n._merge_rank = count
+
+ #setup our sacks
+- self.yumbase._getSacks(archlist=self.archlist)
++ try:
++ self.yumbase._getSacks(archlist=self.archlist)
++ except yum.Errors.RepoError, e:
++ raise MDError, "Could not setup merge repo pkgsack: %s" % e
+
+ myrepos = self.yumbase.repos.listEnabled()
+
+@@ -102,11 +108,16 @@ class RepoMergeBase:
+ def write_metadata(self, outputdir=None):
+ mytempdir = tempfile.mkdtemp()
+ if self.groups:
+- comps_fn = mytempdir + '/groups.xml'
+- compsfile = open(comps_fn, 'w')
+- compsfile.write(self.yumbase.comps.xml())
+- compsfile.close()
+- self.mdconf.groupfile=comps_fn
++ try:
++ comps_fn = mytempdir + '/groups.xml'
++ compsfile = open(comps_fn, 'w')
++ compsfile.write(self.yumbase.comps.xml())
++ compsfile.close()
++ except yum.Errors.GroupsError, e:
++ # groups not being available shouldn't be a fatal error
++ pass
++ else:
++ self.mdconf.groupfile=comps_fn
+
+ if self.updateinfo:
+ ui_fn = mytempdir + '/updateinfo.xml'
diff --git a/createrepo/readMetadata.py b/createrepo/readMetadata.py
index 27d3690..88e5d95 100644
--- a/createrepo/readMetadata.py
@@ -443,6 +615,231 @@ index 27d3690..88e5d95 100644
+ print po.xml_dump_filelists_metadata()
+ print po.xml_dump_other_metadata()
+
+diff --git a/docs/createrepo.8 b/docs/createrepo.8
+index e3c4c3b..96b5bf8 100644
+--- a/docs/createrepo.8
++++ b/docs/createrepo.8
+@@ -53,7 +53,8 @@ gullible).
+ Don't generate repo metadata, if their timestamps are newer than its rpms.
+ This option decreases the processing time drastically again, if you happen
+ to run it on an unmodified repo, but it is (currently) mutual exclusive
+-with the --split option.
++with the --split option. NOTE: This command will not notice when
++packages have been removed from repo. Use --update to handle that.
+ .br
+ .IP "\fB\--split\fP"
+ Run in split media mode. Rather than pass a single directory, take a set of
+diff --git a/genpkgmetadata.py b/genpkgmetadata.py
+index 8c98191..512420b 100755
+--- a/genpkgmetadata.py
++++ b/genpkgmetadata.py
+@@ -100,6 +100,8 @@ def parse_args(args, conf):
+ parser.add_option("--simple-md-filenames", dest="simple_md_filenames",
+ help="do not include the file's checksum in the filename, helps with proxies",
+ default=False, action="store_true")
++ parser.add_option("--retain-old-md", default=0, type='int', dest='retain_old_md',
++ help="keep around the latest (by timestamp) N copies of the old repodata")
+ parser.add_option("--distro", default=[], action="append",
+ help="distro tag and optional cpeid: --distro" "'cpeid,textname'")
+ parser.add_option("--content", default=[], dest='content_tags',
+@@ -240,6 +242,7 @@ def main(args):
+ if mdgen.checkTimeStamps():
+ if mdgen.conf.verbose:
+ print _('repo is up to date')
++ mdgen._cleanup_tmp_repodata_dir()
+ sys.exit(0)
+
+ if conf.profile:
+diff --git a/mergerepo.py b/mergerepo.py
+index 05e5f5e..069a70b 100755
+--- a/mergerepo.py
++++ b/mergerepo.py
+@@ -18,6 +18,7 @@
+
+ import sys
+ import createrepo.merge
++from createrepo.utils import MDError
+ from optparse import OptionParser
+
+ #TODO:
+@@ -77,9 +78,12 @@ def main(args):
+ rmbase.groups = False
+ if opts.noupdateinfo:
+ rmbase.updateinfo = False
+-
+- rmbase.merge_repos()
+- rmbase.write_metadata()
+-
++ try:
++ rmbase.merge_repos()
++ rmbase.write_metadata()
++ except MDError, e:
++ print >> sys.stderr, "Could not merge repos: %s" % e
++ sys.exit(1)
++
+ if __name__ == "__main__":
+ main(sys.argv[1:])
+diff --git a/modifyrepo.py b/modifyrepo.py
+index 17094a4..c3370e8 100755
+--- a/modifyrepo.py
++++ b/modifyrepo.py
+@@ -1,11 +1,15 @@
+ #!/usr/bin/python
+-# This tools is used to insert arbitrary metadata into an RPM repository.
++# This tool is used to manipulate arbitrary metadata in a RPM repository.
+ # Example:
+ # ./modifyrepo.py updateinfo.xml myrepo/repodata
++# or
++# ./modifyrepo.py --remove updateinfo.xml myrepo/repodata
+ # or in Python:
+ # >>> from modifyrepo import RepoMetadata
+ # >>> repomd = RepoMetadata('myrepo/repodata')
+ # >>> repomd.add('updateinfo.xml')
++# or
++# >>> repomd.remove('updateinfo.xml')
+ #
+ # 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
+@@ -20,6 +24,7 @@
+ # (C) Copyright 2006 Red Hat, Inc.
+ # Luke Macken <lmacken at redhat.com>
+ # modified by Seth Vidal 2008
++# modified by Daniel Mach 2011
+
+ import os
+ import sys
+@@ -49,6 +54,35 @@ class RepoMetadata:
+ except RepoMDError, e:
+ raise MDError, 'Could not parse %s' % self.repomdxml
+
++ def _get_mdtype(self, mdname, mdtype=None):
++ """ Get mdtype from existing mdtype or from a mdname. """
++ if mdtype:
++ return mdtype
++ return mdname.split('.')[0]
++
++ def _print_repodata(self, repodata):
++ """ Print repodata details. """
++ print " type =", repodata.type
++ print " location =", repodata.location[1]
++ print " checksum =", repodata.checksum[1]
++ print " timestamp =", repodata.timestamp
++ print " open-checksum =", repodata.openchecksum[1]
++
++ def _write_repomd(self):
++ """ Write the updated repomd.xml. """
++ outmd = file(self.repomdxml, 'w')
++ outmd.write(self.repoobj.dump_xml())
++ outmd.close()
++ print "Wrote:", self.repomdxml
++
++ def _remove_repodata_file(self, repodata):
++ """ Remove a file specified in repodata location """
++ try:
++ os.remove(repodata.location[1])
++ except OSError, ex:
++ if ex.errno != 2:
++ # continue on a missing file
++ raise MDError("could not remove file %s" % repodata.location[1])
+
+ def add(self, metadata, mdtype=None):
+ """ Insert arbitrary metadata into this repository.
+@@ -78,9 +112,8 @@ class RepoMetadata:
+ ## Compress the metadata and move it into the repodata
+ if not mdname.endswith('.gz'):
+ mdname += '.gz'
+- if not mdtype:
+- mdtype = mdname.split('.')[0]
+-
++ mdtype = self._get_mdtype(mdname, mdtype)
++
+ destmd = os.path.join(self.repodir, mdname)
+ newmd = GzipFile(filename=destmd, mode='wb')
+ newmd.write(md)
+@@ -91,11 +124,8 @@ class RepoMetadata:
+ csum, destmd = checksum_and_rename(destmd, self.checksum_type)
+ base_destmd = os.path.basename(destmd)
+
+-
+- ## Remove any stale metadata
+- if mdtype in self.repoobj.repoData:
+- del self.repoobj.repoData[mdtype]
+-
++ # Remove any stale metadata
++ old_rd = self.repoobj.repoData.pop(mdtype, None)
+
+ new_rd = RepoData()
+ new_rd.type = mdtype
+@@ -105,18 +135,28 @@ class RepoMetadata:
+ new_rd.size = str(os.stat(destmd).st_size)
+ new_rd.timestamp = str(os.stat(destmd).st_mtime)
+ self.repoobj.repoData[new_rd.type] = new_rd
+-
+- print " type =", new_rd.type
+- print " location =", new_rd.location[1]
+- print " checksum =", new_rd.checksum[1]
+- print " timestamp =", new_rd.timestamp
+- print " open-checksum =", new_rd.openchecksum[1]
+-
+- ## Write the updated repomd.xml
+- outmd = file(self.repomdxml, 'w')
+- outmd.write(self.repoobj.dump_xml())
+- outmd.close()
+- print "Wrote:", self.repomdxml
++ self._print_repodata(new_rd)
++ self._write_repomd()
++
++ if old_rd is not None and old_rd.location[1] != new_rd.location[1]:
++ # remove the old file when overwriting metadata
++ # with the same mdtype but different location
++ self._remove_repodata_file(old_rd)
++
++ def remove(self, metadata, mdtype=None):
++ """ Remove metadata from this repository. """
++ mdname = metadata
++ mdtype = self._get_mdtype(mdname, mdtype)
++
++ old_rd = self.repoobj.repoData.pop(mdtype, None)
++ if old_rd is None:
++ print "Metadata not found: %s" % mdtype
++ return
++
++ self._remove_repodata_file(old_rd)
++ print "Removed:"
++ self._print_repodata(old_rd)
++ self._write_repomd()
+
+
+ def main(args):
+@@ -124,7 +164,9 @@ def main(args):
+ # query options
+ parser.add_option("--mdtype", dest='mdtype',
+ help="specific datatype of the metadata, will be derived from the filename if not specified")
+- parser.usage = "modifyrepo [options] <input_metadata> <output repodata>"
++ parser.add_option("--remove", action="store_true",
++ help="remove specified file from repodata")
++ parser.usage = "modifyrepo [options] [--remove] <input_metadata> <output repodata>"
+
+ (opts, argsleft) = parser.parse_args(args)
+ if len(argsleft) != 2:
+@@ -137,6 +179,17 @@ def main(args):
+ except MDError, e:
+ print "Could not access repository: %s" % str(e)
+ return 1
++
++ # remove
++ if opts.remove:
++ try:
++ repomd.remove(metadata)
++ except MDError, ex:
++ print "Could not remove metadata: %s" % (metadata, str(ex))
++ return 1
++ return
++
++ # add
+ try:
+ repomd.add(metadata, mdtype=opts.mdtype)
+ except MDError, e:
diff --git a/worker.py b/worker.py
index eb35ef7..ab78d90 100755
--- a/worker.py
diff --git a/createrepo.spec b/createrepo.spec
index 3b10489..e27cfe8 100644
--- a/createrepo.spec
+++ b/createrepo.spec
@@ -3,7 +3,7 @@
Summary: Creates a common metadata repository
Name: createrepo
Version: 0.9.9
-Release: 5%{?dist}
+Release: 6%{?dist}
License: GPLv2
Group: System Environment/Base
Source: %{name}-%{version}.tar.gz
@@ -47,6 +47,10 @@ rm -rf $RPM_BUILD_ROOT
%{python_sitelib}/createrepo
%changelog
+* Fri Jul 29 2011 Seth Vidal <skvidal at fedoraproject.org> - 0.9.9-6
+- latest upstream
+- fixes bugs: 713747, 581632, 581628
+
* Wed Jul 20 2011 Seth Vidal <skvidal at fedoraproject.org> - 0.9.9-5
- new patch to fix us breaking certain pungi configs
More information about the scm-commits
mailing list