Hello community,

here is the log from the commit of package createrepo for openSUSE:Factory 
checked in at 2016-03-29 09:51:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/createrepo (Old)
 and      /work/SRC/openSUSE:Factory/.createrepo.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "createrepo"

Changes:
--------
--- /work/SRC/openSUSE:Factory/createrepo/createrepo.changes    2014-11-24 
11:13:16.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.createrepo.new/createrepo.changes       
2016-03-29 09:51:13.000000000 +0200
@@ -1,0 +2,17 @@
+Wed Dec 30 16:03:29 UTC 2015 - p.drou...@gmail.com
+
+- Update to version 0.10.4
+  * Support API users that set pkglist=<package sack>.(bzrh#1058975)
+  * Add options for parallel deltarpm creation.
+  * Tweak work queue action logging.
+  * Fix several AttributeErrors in RepoMetadata.add().
+  * Fix open_checksum and open_size calculation in RepoMetadata.add().
+  * Allow 'sha' checksum type for modifyrepo.
+  * Improve package description. BZ 1088886
+  * Add options to modifyrepo and mergerepo manpages. (bzrh#1093713)
+- Remove createrepo-0.10.3-modifyrepo-sha.patch; fixed on upstream
+  release
+- Adapt createrepo-0.10.3-fix_MetaDataGenerator.patch to upstream
+  changes > createrepo-fix_MetaDataGenerator.patch
+
+-------------------------------------------------------------------

Old:
----
  createrepo-0.10.3-fix_MetaDataGenerator.patch
  createrepo-0.10.3-modifyrepo-sha.patch
  createrepo-0.10.3.tar.gz

New:
----
  createrepo-0.10.4.tar.gz
  createrepo-fix_MetaDataGenerator.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ createrepo.spec ++++++
--- /var/tmp/diff_new_pack.HQNhp8/_old  2016-03-29 09:51:14.000000000 +0200
+++ /var/tmp/diff_new_pack.HQNhp8/_new  2016-03-29 09:51:14.000000000 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package createrepo
 #
-# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           createrepo
-Version:        0.10.3
+Version:        0.10.4
 Release:        0
 Summary:        Creates a Common Metadata Repository
 License:        GPL-2.0+
@@ -30,8 +30,7 @@
 Patch4:         createrepo-0.9.9-sort-packages-before-writing-repodata.patch
 Patch5:         createrepo-0.9.9-disable-symlinks.patch
 Patch6:         createrepo-0.9.9-by_default_no_database.patch
-Patch7:         createrepo-0.10.3-modifyrepo-sha.patch
-Patch8:         createrepo-0.10.3-fix_MetaDataGenerator.patch
+Patch8:         createrepo-fix_MetaDataGenerator.patch
 BuildRequires:  python-devel
 Requires:       python-deltarpm
 Requires:       python-lxml
@@ -54,7 +53,6 @@
 %patch4 -p1
 %patch5
 %patch6
-%patch7
 %patch8 -p1
 sed -i "1d" createrepo/{readMetadata,yumbased,utils,deltarpms,merge}.py # Fix 
non-executable scripts (remove she-bang line)
 

++++++ createrepo-0.10.3.tar.gz -> createrepo-0.10.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/createrepo-0.10.3/ChangeLog 
new/createrepo-0.10.4/ChangeLog
--- old/createrepo-0.10.3/ChangeLog     2014-01-28 13:28:48.000000000 +0100
+++ new/createrepo-0.10.4/ChangeLog     2015-03-13 13:50:29.000000000 +0100
@@ -1,3 +1,13 @@
+2015-03-13  Valentina Mukhamedzhanova <vmukh...@redhat.com>
+       * Support API users that set pkglist=<package sack>. BZ 1058975
+       * Add options for parallel deltarpm creation.
+       * Tweak work queue action logging.
+       * Fix several AttributeErrors in RepoMetadata.add().
+       * Fix open_checksum and open_size calculation in RepoMetadata.add().
+       * Allow 'sha' checksum type for modifyrepo.
+       * Improve package description. BZ 1088886
+       * Add options to modifyrepo and mergerepo manpages. BZ 1093713
+
 2014-01-28  Zdenek Pavlas <zpav...@redhat.com>
        * createrepo --update: ignore cached rpm when checksum_type
          has changed.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/createrepo-0.10.3/createrepo/__init__.py 
new/createrepo-0.10.4/createrepo/__init__.py
--- old/createrepo-0.10.3/createrepo/__init__.py        2014-01-28 
13:28:49.000000000 +0100
+++ new/createrepo-0.10.4/createrepo/__init__.py        2015-03-13 
13:50:29.000000000 +0100
@@ -28,6 +28,10 @@
 import subprocess
 from select import select
 
+# To support parallel deltarpms
+import multiprocessing
+import multiprocessing.managers
+
 from yum import misc, Errors
 from yum.repoMDObject import RepoMD, RepoData
 from yum.sqlutils import executeSQL
@@ -113,7 +117,10 @@
         #self.worker_cmd = './worker.py' # helpful when testing
         self.retain_old_md = 0
         self.compress_type = 'compat'
-
+        # Parallel deltas additions
+        self.delta_workers = 1 # number of workers to fork when doing deltarpms
+        # Keep the combined payload size of all in-progress deltarpm creation 
below this number
+        self.max_concurrent_delta_rpm_size = self.max_delta_rpm_size
         
 class SimpleMDCallBack(object):
     def errorlog(self, thing):
@@ -400,7 +407,9 @@
         if self.conf.update:
             self._setup_old_metadata_lookup()
         # rpms we're going to be dealing with
-        if self.conf.pkglist:
+        if isinstance(self.conf.pkglist, MetaSack):
+            packages = self.conf.pkglist
+        elif self.conf.pkglist:
             packages = []
             for pkg in self.conf.pkglist:
                 if '://' in pkg: # remote
@@ -716,19 +725,216 @@
             if err:
                 raise MDError, "Failed to process %d package(s)." % err
 
-            for pkgfile in pkgfiles:
-                if self.conf.deltas:
-                    try:
-                        po = self.read_in_package(pkgfile, pkgpath=pkgpath, 
reldir=reldir)
-                        self._do_delta_rpm_package(po)
-                    except MDError, e:
-                        errorprint(e)
-                        continue
-                self.read_pkgs.append(pkgfile)
+            if self.conf.delta_workers == 1:
+                for pkgfile in pkgfiles:
+                    if self.conf.deltas:
+                        try:
+                            po = self.read_in_package(pkgfile, 
pkgpath=pkgpath, reldir=reldir)
+                            self._do_delta_rpm_package(po)
+                        except MDError, e:
+                            errorprint(e)
+                            continue
+                    self.read_pkgs.append(pkgfile)
+            else:
+                self._parallel_deltas(pkgfiles, pkgpath, reldir)
 
         save_keptpkgs(None) # append anything left
         return self.current_pkg
 
+    def _parallel_deltas(self, pkgfiles, pkgpath, reldir):
+        class WrappedMDCallBack(object):
+            def __init__(self, log_queue):
+                self.log_queue = log_queue
+            def errorlog(self, thing):
+                self.log_queue.put([ "errorlog", os.getpid(), thing ])
+
+            def log(self, thing):
+                self.log_queue.put([ "log", os.getpid(), thing ])
+
+            def progress(self, item, current, total):
+                # progress messages in a multiprocess context are likely to 
just be a confusing mess
+                pass
+
+        # Init a few things that we'd rather do in the main process and then
+        # inherit in the children
+        if not hasattr(self, 'tempdir'):
+            self.tempdir = tempfile.mkdtemp()
+        self._get_old_package_dict()
+
+        # queue containing packages that are candidates for processing
+        # now within the memory constraints
+        work_queue = multiprocessing.Queue(1)
+
+        # queue containing callback messages from the workers
+        log_queue = multiprocessing.Queue()
+
+        # Event used to allow the manager, when needed, to block for a 
completed task in a worker
+        completion_event = multiprocessing.Event()
+
+        # wrapped callback to pass in to workers
+        callback_wrap = WrappedMDCallBack(log_queue)
+
+        # list containing the completed packages
+        # accessed in children via a Manager and proxy as each child proc
+        # will be appending as it finishes
+        manager = multiprocessing.Manager()
+        read_pkgs_proxy = manager.list()
+
+        # lists used by the package size reading workers
+        pkgfiles_proxy = manager.list(pkgfiles)
+        pkgfiles_withsize_proxy = manager.list()
+
+        # process-safe value - total size of RPM payloads being deltaed
+        # The lock for entry into this also functions as our critical section
+        # elsewhere, as changes in the "in-flight" size of deltas is the key
+        # decision point in our work queue
+        # 'L' is unsigned long
+        active_work_size = multiprocessing.Value('L',0)
+
+        # Our candidate list is the packages sorted from largest to smallest
+        # Do this with workers as well because, parallel is good
+        # Seriously though, this is also CPU-bound
+        self.callback.log("Reading package sizes in preparation for deltarpm 
creation")
+
+        def size_reader_entry(pkgfiles_proxy, pkgpath, reldir, 
pkgfiles_withsize_proxy, repo_obj):
+            while True:
+                try:
+                    pkgfile = pkgfiles_proxy.pop()
+                    po = repo_obj.read_in_package(pkgfile, pkgpath=pkgpath, 
reldir=reldir)
+                    pkgfiles_withsize_proxy.append([ pkgfile, po.size ])
+                except IndexError:
+                    break
+
+        sort_workers = [ ]
+        for i in range(0,self.conf.delta_workers):
+            sw = multiprocessing.Process(target = size_reader_entry, args = 
(pkgfiles_proxy, pkgpath, reldir, pkgfiles_withsize_proxy, self))
+            sort_workers.append(sw)
+            sw.start()
+
+        for worker in sort_workers:
+            worker.join()
+
+        self.callback.log("Sorting package files by size")
+        sorted_packages = sorted(pkgfiles_withsize_proxy, key=lambda package: 
package[1], reverse=True)
+
+        def worker_entry(work_queue, log_queue, read_pkgs_proxy, repo_obj, 
callback_wrap, active_work_size, completion_event, pkgpath, reldir):
+            # We are now a new process - replace the callback with the wrapper 
that pushes log messages
+            # to a queue for processing in the main process
+            repo_obj.callback = callback_wrap
+            while True:
+                try:
+                    pkg = None
+                    pkg = work_queue.get()
+                    if not pkg:
+                        # The manager feeds each worker a None to indicate we 
are finished
+                        # this allows us to use a blocking get without fear - 
I think
+                        break
+                    po = repo_obj.read_in_package(pkg[0], pkgpath=pkgpath, 
reldir=reldir)
+                    repo_obj._do_delta_rpm_package(po)
+                except Exception, e:
+                    callback_wrap.errorlog(e)
+                    continue
+                finally:
+                    if pkg:
+                        with active_work_size.get_lock():
+                            active_work_size.value -= pkg[1]
+                            completion_event.set()
+                        read_pkgs_proxy.append(pkg)
+
+        def manager_entry(packages, active_work_size, log_queue, 
completion_event, work_queue, callback_wrap, read_pkgs_proxy, repo_obj, 
pkgpath, reldir):
+            max_work_size = repo_obj.conf.max_concurrent_delta_rpm_size
+            num_workers = repo_obj.conf.delta_workers
+            workers = [ ]
+            callback_wrap.log("Starting %d workers to process deltarpms - max 
total work size (%d) bytes" % (num_workers, max_work_size))
+            for i in range(0,repo_obj.conf.delta_workers):
+                wp = multiprocessing.Process(target = worker_entry, args = 
(work_queue, log_queue, read_pkgs_proxy, repo_obj, callback_wrap, 
active_work_size, completion_event, pkgpath, reldir))
+                workers.append(wp)
+                wp.start()
+
+            pending_packages = 0
+            while len(packages) > 0:
+                # Look through the package list and add things that fit under 
the max size limit
+                # until we reach the end of the list
+
+                # Don't read shared state for every package - it is an 
expensive operation
+                work_size_snap = active_work_size.value
+                #log_queue.put("Entered main loop with package list of length 
%d and size snap %d" % (len(packages), work_size_snap))
+                consumed = [ ]
+                for i in range(0,len(packages)):
+                    package = packages[i]
+                    if package[1] + work_size_snap < max_work_size:
+                        with active_work_size.get_lock():
+                            # As long as we have the lock we may as well 
refresh our view of the actual size
+                            active_work_size.value += package[1]
+                            #Turn on profiling if you want to convince 
yourself that this really does keep the size sane
+                            if self.conf.profile:
+                                callback_wrap.log("Adding package (%s) of size 
%d to deltarpm work queue" % (package[0], package[1]))
+                                callback_wrap.log("Current TOTAL in-flight 
work size: %d" % (active_work_size.value))
+                                callback_wrap.log("Packages remaining to 
process: %d" % (len(packages)-len(consumed)-1))
+                            work_size_snap = active_work_size.value
+                            # Note that we block here if the queue is full
+                            pending_packages = work_queue.qsize() + 1
+                            consumed.append(i)
+                        # This can block - do it without the lock
+                        work_queue.put(package)
+                # Now prune the added items from the list, going backwards to 
ensure that we don't
+                # shift the index and delete the wrong thing
+                for i in reversed(consumed):
+                    del packages[i]
+                if len(packages) == 0:
+                    break
+
+                with active_work_size.get_lock():
+                    work_queue_size = work_queue.qsize()
+                    if pending_packages > work_queue_size:
+                        # Some work was started since we last touched the 
queue - try to add more
+                        # Note that this guarantees there is at least one free 
slot in the work_queue
+                        # This should also prevent us from constantly spinning 
in the package loop when
+                        # we have space in the queue but not enough 
active_work_size to allow us to add any
+                        # available package
+                        pending_packages = work_queue_size
+                        continue
+                    else:
+                        completion_event.clear()
+
+                # We either have too many items on the work_queue or too much 
total work size
+                # Wait for a worker to finish and then try again
+                completion_event.wait()
+
+            # We are done - tell the workers to stop
+            for worker in workers:
+                work_queue.put(None)
+
+            for worker in workers:
+                worker.join()
+
+            # Now signal to the main thread that we are done adding work
+            log_queue.put(None)
+
+        manager = multiprocessing.Process(target = manager_entry, args = 
(sorted_packages, active_work_size, log_queue, completion_event, work_queue, 
callback_wrap, read_pkgs_proxy, self, pkgpath, reldir))
+        manager.start()
+
+        def log_digest(callback, log_message):
+            if log_message[0] == "errorlog":
+                callback.errorlog("Worker PID(%d) - %s" % (log_message[1], 
log_message[2]))
+            elif log_message[0] == "log":
+                callback.log("Worker PID(%d) - %s" % (log_message[1], 
log_message[2]))
+            else:
+                callback.errorlog("Malformed error in queue (%s)" % 
(str(log_message)))
+
+        # Process log messages until we get the finished signal "None"
+        while True:
+            log_message = log_queue.get()
+            if log_message is None:
+                break
+            log_digest(self.callback, log_message)
+
+        # now empty our proxy list
+        for pkg in read_pkgs_proxy:
+            self.read_pkgs.append(pkg)
+
+        # TODO: we may be able to explicitly stop the Manager at this point
+
 
     def closeMetadataDocs(self):
         # save them up to the tmp locations:
@@ -847,19 +1053,22 @@
         # appending the output. for each of the keys in the dict, return
         # the tag for the target + each of the drpm infos + closure for the 
target
         # tag
-        targets = {}
         results = []
-        for drpm_fn in self.getFileList(self.conf.deltadir, '.drpm'):
-            drpm_rel_fn = os.path.normpath(self.conf.delta_relative +
-                                           '/' + drpm_fn) # this is annoying
-            drpm_po = yumbased.CreateRepoPackage(self.ts,
-                 self.conf.deltadir + '/' + drpm_fn, sumtype=self.conf.sumtype)
-
-            drpm = deltarpms.DeltaRPMPackage(drpm_po, self.conf.outputdir,
-                                             drpm_rel_fn)
-            if not targets.has_key(drpm_po.pkgtup):
-                targets[drpm_po.pkgtup] = []
-            targets[drpm_po.pkgtup].append(drpm.xml_dump_metadata())
+        if self.conf.delta_workers == 1:
+            targets = {}
+            for drpm_fn in self.getFileList(self.conf.deltadir, '.drpm'):
+                drpm_rel_fn = os.path.normpath(self.conf.delta_relative +
+                                               '/' + drpm_fn) # this is 
annoying
+                drpm_po = yumbased.CreateRepoPackage(self.ts,
+                     self.conf.deltadir + '/' + drpm_fn, 
sumtype=self.conf.sumtype)
+
+                drpm = deltarpms.DeltaRPMPackage(drpm_po, self.conf.outputdir,
+                                                 drpm_rel_fn)
+                if not targets.has_key(drpm_po.pkgtup):
+                    targets[drpm_po.pkgtup] = []
+                targets[drpm_po.pkgtup].append(drpm.xml_dump_metadata())
+        else:
+            targets = self._parallel_generate_delta_xml()
 
         for (n, a, e, v, r) in targets.keys():
             results.append("""  <newpackage name="%s" epoch="%s" version="%s" 
release="%s" arch="%s">\n""" % (
@@ -872,6 +1081,52 @@
 
         return ' '.join(results)
 
+    def _parallel_generate_delta_xml(self):
+        drpm_fns = [ ]
+        for drpm_fn in self.getFileList(self.conf.deltadir, '.drpm'):
+            drpm_fns.append(drpm_fn)
+
+        manager = multiprocessing.Manager()
+        drpm_fns_proxy = manager.list(drpm_fns)
+        targets_proxy = manager.dict()
+        targets_lock = manager.RLock()
+
+        def drpm_xml_entry(drpm_fns_proxy, targets_proxy, targets_lock, 
repo_obj):
+            while True:
+                try:
+                    drpm_fn = drpm_fns_proxy.pop()
+                    drpm_rel_fn = 
os.path.normpath(repo_obj.conf.delta_relative +
+                                                   '/' + drpm_fn) # this is 
annoying
+                    drpm_po = yumbased.CreateRepoPackage(repo_obj.ts,
+                         repo_obj.conf.deltadir + '/' + drpm_fn, 
sumtype=repo_obj.conf.sumtype)
+
+                    drpm = deltarpms.DeltaRPMPackage(drpm_po, 
repo_obj.conf.outputdir,
+                                                     drpm_rel_fn)
+
+                    with targets_lock:
+                        d_element = targets_proxy.get(drpm_po.pkgtup, [ ])
+                        d_element.append(drpm.xml_dump_metadata())
+                        # managed dict requires that we re-assign modified 
list rather than modify in place
+                        targets_proxy[drpm_po.pkgtup] = d_element
+                except IndexError:
+                    break
+
+        xml_workers = [ ]
+        for i in range(0,self.conf.delta_workers):
+            xw = multiprocessing.Process(target = drpm_xml_entry, args = 
(drpm_fns_proxy, targets_proxy, targets_lock, self))
+            xml_workers.append(xw)
+            xw.start()
+
+        for worker in xml_workers:
+            worker.join()
+
+        # I'm doing a copy in this way as I believe that prevents references 
to the manager from lingering
+        # TODO: Verify?
+        targets_copy = { }
+        for key in targets_proxy.keys():
+            targets_copy[key] = targets_proxy[key]
+        return targets_copy
+
     def _createRepoDataObject(self, mdfile, mdtype, compress=True, 
                               compress_type=None, attribs={}):
         """return random metadata as RepoData object to be  added to RepoMD
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/createrepo-0.10.3/createrepo.spec 
new/createrepo-0.10.4/createrepo.spec
--- old/createrepo-0.10.3/createrepo.spec       2014-01-28 13:28:48.000000000 
+0100
+++ new/createrepo-0.10.4/createrepo.spec       2015-03-13 13:50:29.000000000 
+0100
@@ -14,7 +14,7 @@
 
 Summary: Creates a common metadata repository
 Name: createrepo
-Version: 0.10.3
+Version: 0.10.4
 Release: 1
 License: GPL
 Group: System Environment/Base
@@ -26,8 +26,8 @@
 Requires: yum-metadata-parser, yum >= 3.2.29, python-deltarpm, pyliblzma
 
 %description
-This utility will generate a common metadata repository from a directory of
-rpm packages
+A set of utilities for generating a common metadata repository
+from a directory of rpm packages and maintaining it.
 
 %prep
 %setup -q
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/createrepo-0.10.3/docs/mergerepo.1 
new/createrepo-0.10.4/docs/mergerepo.1
--- old/createrepo-0.10.3/docs/mergerepo.1      2014-01-28 13:28:49.000000000 
+0100
+++ new/createrepo-0.10.4/docs/mergerepo.1      2015-03-13 13:50:30.000000000 
+0100
@@ -21,7 +21,7 @@
 repository metadata will be written to `pwd`/merged_repo/.
 
 .IP "\fB\-d \-\-database\fP"
-Generate sqlite databases of the merged repository metadata.
+Generate sqlite databases of the merged repository metadata. This is now the 
default.
 
 .IP "\fB\-a \-\-archlist\fP"
 Specify a comma-separated list of architectures to use. Defaults to ALL.
@@ -32,6 +32,17 @@
 .IP "\fB\-\-noupdateinfo\fP"
 Do not merge/include updateinfo metadata in the repository.
 
+.IP "\fB\-\-no-database\fP"
+Do not generate sqlite databases in the repository.
+
+.IP "\fB\-\-compress-type <compress-type>\fP"
+Specify which compression type to use: compat (default), xz (may not be 
available), gz, bz2.
+
+.IP "\fB\-\-version\fP"
+Output version.
+
+.IP "\fB\-h \-\-help\fP"
+Show help menu.
 
 .SH "EXAMPLES"
 .PP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/createrepo-0.10.3/docs/modifyrepo.1 
new/createrepo-0.10.4/docs/modifyrepo.1
--- old/createrepo-0.10.3/docs/modifyrepo.1     2014-01-28 13:28:49.000000000 
+0100
+++ new/createrepo-0.10.4/docs/modifyrepo.1     2015-03-13 13:50:30.000000000 
+0100
@@ -10,6 +10,37 @@
 .SH "DESCRIPTION"
 \fBmodifyrepo\fP is a program that allows you to insert arbitrary metadata 
into a repomd (xml-based rpm metadata) repository.
 
+.SH "OPTIONS"
+.IP "\fB\-\-mdtype <mdtype>\fP"
+Specify datatype of the metadata. If not specified, datatype will be derived 
from the filename.
+
+.IP "\fB\-\-remove\fP"
+Remove specified file from repodata.
+
+.IP "\fB\-\-compress\fP"
+Compress the new repodata before adding it to the repo. This is used by 
default.
+
+.IP "\fB\-\-no-compress\fP"
+Do not compress the new repodata before adding it to the repo.
+
+.IP "\fB\-\-compress-type <compress-type>\fP"
+Specify which compression type to use: compat (default), xz (may not be 
available), gz, bz2.
+
+.IP "\fB\-s, \-\-checksum <sumtype>\fP"
+Specify the checksum type to use.
+
+.IP "\fB\-\-unique-md-filenames\fP"
+Include the file's checksum in the metadata filename, helps with HTTP caching 
(default).
+
+.IP "\fB\-\-simple-md-filenames\fP"
+Do not include the file's checksum in the metadata filename.
+
+.IP "\fB\-\-version\fP"
+Output version.
+
+.IP "\fB\-h \-\-help\fP"
+Show help menu.
+
 .SH "EXAMPLES"
 .PP
 $ \fBmodifyrepo\fP \-\-mdtype=newmd metadata.xml /repository/repodata
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/createrepo-0.10.3/genpkgmetadata.py 
new/createrepo-0.10.4/genpkgmetadata.py
--- old/createrepo-0.10.3/genpkgmetadata.py     2014-01-28 13:28:48.000000000 
+0100
+++ new/createrepo-0.10.4/genpkgmetadata.py     2015-03-13 13:50:29.000000000 
+0100
@@ -128,9 +128,15 @@
     parser.add_option("--max-delta-rpm-size", default=100000000,
         dest='max_delta_rpm_size', type='int',
         help="max size of an rpm that to run deltarpm against (in bytes)")
+    parser.add_option("--max-concurrent-delta-rpm-size", default=100000000,
+        dest='max_concurrent_delta_rpm_size', type='int',
+        help="max total payload size of concurrent deltarpm runs (in bytes)")
     parser.add_option("--workers", default=def_workers,
         dest='workers', type='int',
         help="number of workers to spawn to read rpms")
+    parser.add_option("--delta-workers", default=1,
+        dest='delta_workers', type='int',
+        help="number of workers to spawn to create delta rpms")
     parser.add_option("--xz", default=False,
         action="store_true",
         help=SUPPRESS_HELP)
@@ -155,6 +161,12 @@
     if opts.workers >= 128:
         errorprint(_('Warning: More than 128 workers is a lot. Limiting.'))
         opts.workers = 128
+    if opts.delta_workers > opts.workers:
+        errorprint(_('Warning: Requested more delta workers than workers. This 
is insane. Limiting.'))
+        opts.delta_workers = opts.workers
+    if opts.max_concurrent_delta_rpm_size < opts.max_delta_rpm_size:
+        errorprint(_('Warning: max_concurrent_delta_rpm_size < 
max_delta_rpm_size - this will deadlock. Setting them to the same value.'))
+        opts.max_concurrent_delta_rpm_size = opts.max_delta_rpm_size
     if opts.sumtype == 'sha1':
         errorprint(_('Warning: It is more compatible to use sha instead of 
sha1'))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/createrepo-0.10.3/modifyrepo.py 
new/createrepo-0.10.4/modifyrepo.py
--- old/createrepo-0.10.3/modifyrepo.py 2014-01-28 13:28:48.000000000 +0100
+++ new/createrepo-0.10.4/modifyrepo.py 2015-03-13 13:50:29.000000000 +0100
@@ -37,6 +37,7 @@
 from yum.repoMDObject import RepoMD, RepoMDError, RepoData
 from xml.dom import minidom
 from optparse import OptionParser
+from cStringIO import StringIO
 
 
 class RepoMetadata:
@@ -46,6 +47,9 @@
         self.repodir = os.path.abspath(repo)
         self.repomdxml = os.path.join(self.repodir, 'repomd.xml')
         self.compress_type = _available_compression[-1] # best available
+        self.compress = True
+        self.checksum_type = 'sha256'
+        self.unique_md_filenames = True
 
         if not os.path.exists(self.repomdxml):
             raise MDError, '%s not found' % self.repomdxml
@@ -103,6 +107,8 @@
         if isinstance(metadata, minidom.Document):
             md = metadata.toxml()
             mdname = 'updateinfo.xml'
+            oldmd = AutoFileChecksums(StringIO(md), [self.checksum_type])
+            oldmd.read()
         elif isinstance(metadata, str):
             if os.path.exists(metadata):
                 mdname = os.path.basename(metadata)
@@ -147,7 +153,7 @@
         new_rd.checksum = (self.checksum_type, csum)
         new_rd.size = str(os.stat(destmd).st_size)
         if self.compress:
-            new_rd.openchecksum = oldmd.checksums.hexdigests().popitem()
+            new_rd.openchecksum = (self.checksum_type, 
oldmd.checksums.hexdigests().popitem()[1])
             new_rd.opensize = str(oldmd.checksums.length)
         new_rd.timestamp = str(int(os.stat(destmd).st_mtime))
         self.repoobj.repoData[new_rd.type] = new_rd
@@ -236,7 +242,7 @@
     if opts.compress_type not in _available_compression:
         print "Compression %s not available: Please choose from: %s" % 
(opts.compress_type, ', '.join(_available_compression))
         return 1
-    if opts.sumtype not in _available_checksums:
+    if opts.sumtype != 'sha' and opts.sumtype not in _available_checksums:
         print "Checksum %s not available: Please choose from: %s" % 
(opts.sumtype, ', '.join(_available_checksums))
         return 1
     repomd.compress_type = opts.compress_type

++++++ createrepo-fix_MetaDataGenerator.patch ++++++
Index: createrepo-0.10.3/createrepo/__init__.py
===================================================================
--- createrepo-0.10.3.orig/createrepo/__init__.py
+++ createrepo-0.10.3/createrepo/__init__.py
@@ -412,7 +412,8 @@
         elif self.conf.pkglist:
             packages = []
             for pkg in self.conf.pkglist:
-                if '://' in pkg: # remote
+                if isinstance(pkg, YumAvailablePackage) or '://' in pkg:
+                    # either a package object or a remote file
                     packages.append(pkg)
                     continue
                 path = os.path.join(self.conf.basedir, self.conf.directory, 
pkg)

Reply via email to