--- /dev/null
+#!/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 2008 Red Hat, Inc - written by seth vidal skvidal at fedoraproject.org
+
+# merge repos from arbitrary repo urls
+
+import os
+import shutil
+import yum
+import yum.Errors
+from yum.misc import unique, getCacheDir
+import yum.update_md
+import rpmUtils.arch
+import operator
+import createrepo
+import tempfile
+
+# take repo paths from cli
+# produce new repo metadata from merging the two together.
+
+#TODO:
+# excludes?
+
+
+class RepoMergeBase():
+ def __init__(self, repolist=[]):
+ self.repolist = repolist
+ self.outputdir = '%s/merged_repo' % os.getcwd()
+ self.exclude_tuples = []
+ self.sort_func = self._sort_func # callback function to magically sort pkgs
+ self.mdconf = createrepo.MetaDataConfig()
+ self.yumbase = yum.YumBase()
+ self.yumbase.conf.cachedir = getCacheDir()
+ self.yumbase.conf.cache = 0
+ # default to all arches
+ self.archlist = unique(rpmUtils.arch.arches.keys() + rpmUtils.arch.arches.values())
+ self.groups = True
+ self.updateinfo = True
+
+ def _sort_func(self, repos):
+ """Default sort func for repomerge. Takes a list of repository objects
+ any package which is not to be included in the merged repo should be
+ delPackage()'d"""
+ # sort the repos by _merge_rank
+ # - lowest number is the highest rank (1st place, 2ndplace, etc)
+ repos.sort(key=operator.attrgetter('_merge_rank'))
+
+ for repo in repos:
+ for pkg in repo.sack:
+ others = self.yumbase.pkgSack.searchNevra(name=pkg.name, arch=pkg.arch)
+ # NOTE the above is definitely going to catch other versions which may
+ # be an invalid comparison
+ if len(others) > 1:
+ for thatpkg in others:
+ if pkg.repoid == thatpkg.repoid: continue
+ if pkg.repo._merge_rank < thatpkg.repo._merge_rank:
+ thatpkg.repo.sack.delPackage(thatpkg)
+
+ def merge_repos(self):
+ self.yumbase.repos.disableRepo('*')
+ # add our repos and give them a merge rank in the order they appear in
+ # in the repolist
+ count = 0
+ for r in self.repolist:
+ count +=1
+ rid = 'repo%s' % count
+ n = self.yumbase.add_enable_repo(rid, baseurls=[r])
+ n._merge_rank = count
+
+ #setup our sacks
+ self.yumbase._getSacks(archlist=self.archlist)
+
+ myrepos = self.yumbase.repos.listEnabled()
+
+ self.sort_func(myrepos)
+
+
+ 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
+
+ if self.updateinfo:
+ ui_fn = mytempdir + '/updateinfo.xml'
+ uifile = open(ui_fn, 'w')
+ umd = yum.update_md.UpdateMetadata()
+ for repo in self.yumbase.repos.listEnabled():
+ try: # attempt to grab the updateinfo.xml.gz from the repodata
+ umd.add(repo)
+ except yum.Errors.RepoMDError:
+ continue
+ umd.xml(fileobj=uifile)
+ uifile.close()
+ self.mdconf.additional_metadata['updateinfo'] = ui_fn
+
+
+ self.mdconf.pkglist = self.yumbase.pkgSack
+ self.mdconf.directory = self.outputdir
+ if outputdir:
+ self.mdconf.directory = outputdir
+ # clean out what was there
+ if os.path.exists(self.mdconf.directory + '/repodata'):
+ shutil.rmtree(self.mdconf.directory + '/repodata')
+
+ if not os.path.exists(self.mdconf.directory):
+ os.makedirs(self.mdconf.directory)
+
+ mdgen = createrepo.MetaDataGenerator(config_obj=self.mdconf)
+ mdgen.doPkgMetadata()
+ mdgen.doRepoMetadata()
+ mdgen.doFinalMove()
--- /dev/null
+#!/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 2008 Red Hat, Inc - written by seth vidal skvidal at fedoraproject.org
+
+# merge repos from arbitrary repo urls
+
+import sys
+import createrepo.merge
+from optparse import OptionParser
+
+#TODO:
+# excludes?
+
+def parse_args(args):
+ usage = """
+ mergerepo: take 2 or more repositories and merge their metadata into a new repo
+
+ mergerepo --repo=url --repo=url --outputdir=/some/path"""
+
+ parser = OptionParser(version = "mergerepo 0.1", usage=usage)
+ # query options
+ parser.add_option("-r", "--repo", dest='repos', default=[], action="append",
+ help="repo url")
+ parser.add_option("-a", "--archlist", default=[], action="append",
+ help="Defaults to all arches - otherwise specify arches")
+ parser.add_option("-d", "--database", default=False, action="store_true")
+ parser.add_option("-o", "--outputdir", default=None,
+ help="Location to create the repository")
+ parser.add_option("", "--nogroups", default=False, action="store_true",
+ help="Do not merge group(comps) metadata")
+ parser.add_option("", "--noupdateinfo", default=False, action="store_true",
+ help="Do not merge updateinfo metadata")
+ (opts, argsleft) = parser.parse_args()
+
+ if len(opts.repos) < 2:
+ parser.print_usage()
+ sys.exit(1)
+
+ # sort out the comma-separated crap we somehow inherited.
+ archlist = []
+ for a in opts.archlist:
+ for arch in a.split(','):
+ archlist.append(arch)
+
+ opts.archlist = archlist
+
+ return opts
+
+def main(args):
+ opts = parse_args(args)
+ rm = createrepo.merge.RepoMergeBase(opts.repos)
+ if opts.archlist:
+ rm.archlist = opts.archlist
+ if opts.outputdir:
+ rm.outputdir = opts.outputdir
+ if opts.database:
+ rm.mdconf.database = True
+ if opts.nogroups:
+ rm.groups = False
+ if opts.noupdateinfo:
+ rm.updateinfo = False
+
+ rm.merge_repos()
+ rm.write_metadata()
+
+if __name__ == "__main__":
+ main(sys.argv[1:])