diff --git a/SOURCES/BZ-1127783-transaction-actions-fix-file-globs.patch b/SOURCES/BZ-1127783-transaction-actions-fix-file-globs.patch new file mode 100644 index 0000000..718c55c --- /dev/null +++ b/SOURCES/BZ-1127783-transaction-actions-fix-file-globs.patch @@ -0,0 +1,83 @@ +diff -up yum-utils-1.1.31/plugins/post-transaction-actions/post-transaction-actions.py.orig yum-utils-1.1.31/plugins/post-transaction-actions/post-transaction-actions.py +--- yum-utils-1.1.31/plugins/post-transaction-actions/post-transaction-actions.py.orig 2017-11-03 16:26:49.762703946 +0100 ++++ yum-utils-1.1.31/plugins/post-transaction-actions/post-transaction-actions.py 2017-11-03 16:26:53.607688349 +0100 +@@ -139,7 +139,6 @@ def posttrans_hook(conduit): + c_string = re.compile(restring) + + for txmbr in pkgset: +- matched = False + thispo = txmbr.po + if txmbr.output_state in TS_INSTALL_STATES: + # thispo is AvailablePackage; filelist access could trigger download +@@ -150,17 +149,13 @@ def posttrans_hook(conduit): + if a_k in thispo.filelist + thispo.dirlist + thispo.ghostlist: + thiscommand = _convert_vars(txmbr, a_c) + commands_to_run[thiscommand] = 1 +- matched = True ++ break + else: + for name in thispo.filelist + thispo.dirlist + thispo.ghostlist: + if c_string.match(name): + thiscommand = _convert_vars(txmbr, a_c) + commands_to_run[thiscommand] = 1 +- matched = True + break +- +- if matched: +- break + continue + + if a_k.find('/') == -1: # pkgspec +diff -up yum-utils-1.1.31/plugins/post-transaction-actions/sample.action.orig yum-utils-1.1.31/plugins/post-transaction-actions/sample.action +--- yum-utils-1.1.31/plugins/post-transaction-actions/sample.action.orig 2011-08-10 17:20:19.000000000 +0200 ++++ yum-utils-1.1.31/plugins/post-transaction-actions/sample.action 2017-11-03 16:26:53.607688349 +0100 +@@ -19,3 +19,8 @@ zsh:install:touch /tmp/zsh-installed-als + /bin/z*h:install:touch /tmp/bin-zsh-installed + z*h:any:touch /tmp/bin-zsh-any + ++# each action is expanded once for each matching package, and no action is ++# executed twice per transaction, for example ++*:install:echo $repoid >>/tmp/repos ++# will write each repo only once to /tmp/repos, even if multiple packages from ++# the same repo were installed +diff -up yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py.orig yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py +--- yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py.orig 2017-11-03 16:26:49.819703715 +0100 ++++ yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py 2017-11-03 16:26:53.609688341 +0100 +@@ -120,24 +120,19 @@ def pretrans_hook(conduit): + c_string = re.compile(restring) + + for txmbr in pkgset: +- matched = False + thispo = txmbr.po + + if not yum.misc.re_glob(a_k): + if a_k in thispo.filelist + thispo.dirlist + thispo.ghostlist: + thiscommand = _convert_vars(txmbr, a_c) + commands_to_run[thiscommand] = 1 +- matched = True ++ break + else: + for name in thispo.filelist + thispo.dirlist + thispo.ghostlist: + if c_string.match(name): + thiscommand = _convert_vars(txmbr, a_c) + commands_to_run[thiscommand] = 1 +- matched = True + break +- +- if matched: +- break + continue + + if a_k.find('/') == -1: # pkgspec +diff -up yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action.orig yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action +--- yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action.orig 2017-11-03 16:26:49.820703711 +0100 ++++ yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action 2017-11-03 16:26:53.609688341 +0100 +@@ -19,3 +19,8 @@ zsh:install:touch /tmp/zsh-installed-als + /bin/z*h:install:touch /tmp/bin-zsh-installed + z*h:any:touch /tmp/bin-zsh-any + ++# each action is expanded once for each matching package, and no action is ++# executed twice per transaction, for example ++*:install:echo $repoid >>/tmp/repos ++# will write each repo only once to /tmp/repos, even if multiple packages from ++# the same repo are going to be installed diff --git a/SOURCES/BZ-1333353-verifytree-fix-handling-no-comps.patch b/SOURCES/BZ-1333353-verifytree-fix-handling-no-comps.patch new file mode 100644 index 0000000..b85822b --- /dev/null +++ b/SOURCES/BZ-1333353-verifytree-fix-handling-no-comps.patch @@ -0,0 +1,33 @@ +commit 56c7eacd9d0ad9237d05e1393c12d5059edb2c7a +Author: Michal Domonkos +Date: Mon Oct 23 15:33:13 2017 +0200 + + verifytree: fix handling of missing comps. BZ 1333353 + + When we have group_command = 'objects' and no comps file, invoking + my.comps doesn't raise a GroupsError as we would expect, and we continue + to newrepo.getGroups() where we finally traceback. This commit makes + sure we detect that beforehand and fail correctly. + +diff --git a/verifytree.py b/verifytree.py +index 6a127cd..7f11f10 100755 +--- a/verifytree.py ++++ b/verifytree.py +@@ -237,7 +237,8 @@ def main(): + try: + print " verifying comps.xml with yum" + b = my.comps.compscount +- except Errors.GroupsError, e: ++ comps = newrepo.getGroups() ++ except (Errors.GroupsError, Errors.RepoMDError): + print ' comps file missing or unparseable' + report('COMPS','FAILED') + retval = retval | BAD_COMPS +@@ -254,7 +255,6 @@ def main(): + 'properly installed') + r = 1 + else: +- comps = newrepo.getGroups() + r = os.system("xmllint --noout --nowarning --relaxng %s %s" % + (schema, comps)) + if r != 0: diff --git a/SOURCES/BZ-1349433-verifytree-handle-no-core-group.patch b/SOURCES/BZ-1349433-verifytree-handle-no-core-group.patch new file mode 100644 index 0000000..f2a7af9 --- /dev/null +++ b/SOURCES/BZ-1349433-verifytree-handle-no-core-group.patch @@ -0,0 +1,32 @@ +commit b586ff502946fbd3271db8370cb546f696c51cfd +Author: Michal Domonkos +Date: Fri Oct 20 19:47:36 2017 +0200 + + verifytree: handle no @core group gracefully. BZ 1349433 + + It's not clear to me whether @core group is really mandatory, however + let's make verifytree fail if it's not defined so that we don't change + the return code to 0 for that case; we would return 1 previously (python + traceback) and now we OR the BAD_COMPS flag which is 4 (still not 1 but + at least non-zero). + +diff --git a/verifytree.py b/verifytree.py +index 6a127cd..603a633 100755 +--- a/verifytree.py ++++ b/verifytree.py +@@ -278,7 +278,14 @@ def main(): + elif not (retval & BAD_COMPS or opts.nocomps): + print "Checking mandatory @core packages" + group = my.comps.return_group('core') +- for pname in group.mandatory_packages: ++ if group is not None: ++ pkgs = group.mandatory_packages ++ else: ++ print " @core group not found" ++ retval = retval | BAD_COMPS ++ report('COMPS','FAILED') ++ pkgs = [] ++ for pname in pkgs: + # FIXME: this pulls from pkgSack, which (I guess) is populated + # based on the arch etc. of the current host.. so you can't check + # the x86_64 repo from an i386 machine, f'rinstance. diff --git a/SOURCES/BZ-1428210-fastestmirror-use-prereposetup.patch b/SOURCES/BZ-1428210-fastestmirror-use-prereposetup.patch new file mode 100644 index 0000000..f8f4b52 --- /dev/null +++ b/SOURCES/BZ-1428210-fastestmirror-use-prereposetup.patch @@ -0,0 +1,68 @@ +commit f62ca0e78ff5b087c0cb49d858e040a5c5284eeb +Author: Michal Domonkos +Date: Mon Jun 5 20:29:10 2017 +0200 + + fastestmirror: move the logic before MD retrieval. BZ 1428210 + + This plugin has had no effect on metadata downloads since commit a522869 + in yum where we put a RepoStorage.retrieveAllMD() call before + postreposetup_hook used by this plugin. Let's change to using + prereposetup_hook instead so that retrieveAllMD() can make use of the + sorted urls. + + In practice, though, mirrors would still be benchmarked and sorted + because of a similar mechanism present in urlgrabber (the timedhosts + option, always enabled in yum) with one exception: If the yum cache is + empty (no timedhosts file yet), the original order received from the + server would be retained (a property of stable sorting [1]) for the + repomd.xml download, which is still a bad situation that wouldn't happen + before a522869; this is fixed with this commit as it allows the plugin + to do its work beforehand. + + Note that the stuff we do in yum/repos.py in between prereposetup_hook + and postreposetup_hook has nothing to do with our plugin anyway, so we + won't "miss" or break any configuration steps when we move our logic + from the latter to the former location. + + [1] urlgrabber/mirror.py:275 + +diff --git a/plugins/fastestmirror/fastestmirror.py b/plugins/fastestmirror/fastestmirror.py +index fe79629..5887e32 100644 +--- a/plugins/fastestmirror/fastestmirror.py ++++ b/plugins/fastestmirror/fastestmirror.py +@@ -146,7 +146,7 @@ def _len_non_ftp(urls): + num += 1 + return num + +-def postreposetup_hook(conduit): ++def prereposetup_hook(conduit): + """ + This function is called after Yum has initiliazed all the repository information. + +@@ -255,7 +255,7 @@ def read_timedhosts(): + communicate with other functions. + + This function is referred by: +- - L{postreposetup_hook()} ++ - L{prereposetup_hook()} + + @param timedhosts : A list of time intervals to reach different hosts + corresponding to the mirrors. The index of the list are hostnames. +@@ -281,7 +281,7 @@ def write_timedhosts(): + communicate with other functions. + + This function is referred by: +- - L{postreposetup_hook()} ++ - L{prereposetup_hook()} + + @param timedhosts : A list of time intervals to reach different hosts + corresponding to the mirrors. The index of the list are hostnames. +@@ -359,7 +359,7 @@ class FastestMirror: + - L{FastestMirror._poll_mirrors()} + + This function is referred by: +- - L{postreposetup_hook()} ++ - L{prereposetup_hook()} + - L{main()} + + @rtype: List diff --git a/SOURCES/BZ-1437636-yum-builddep-add-define-opt.patch b/SOURCES/BZ-1437636-yum-builddep-add-define-opt.patch new file mode 100644 index 0000000..f8a6030 --- /dev/null +++ b/SOURCES/BZ-1437636-yum-builddep-add-define-opt.patch @@ -0,0 +1,64 @@ +diff --git a/docs/yum-builddep.1 b/docs/yum-builddep.1 +index fbe32bd..54dce0e 100644 +--- a/docs/yum-builddep.1 ++++ b/docs/yum-builddep.1 +@@ -17,6 +17,12 @@ disabled) or it can be a local source RPM or a spec file. + .PP + Note, that only the BuildRequires information within the SRPM header information is used to determine build dependencies. This will specifically omit any dependencies that are required only for specific architectures. + .PP ++.SH "GENERAL OPTIONS" ++.IP "\fB\--target ARCH\fP" ++Set target architecture for spec parsing. ++.IP "\fB\--define 'MACRO EXPR'\fP" ++Define the rpm MACRO with value EXPR for spec parsing. ++.PP + .SH "EXAMPLES" + .IP "Download and install all the RPMs needed to build the kernel RPM:" + \fByumdownloader --source kernel && rpm2cpio kernel*src.rpm | cpio -i kernel.spec && \\ \fP +diff --git a/yum-builddep.py b/yum-builddep.py +index 5f59ab8..dfdd31b 100755 +--- a/yum-builddep.py ++++ b/yum-builddep.py +@@ -67,6 +67,13 @@ class YumBuildDep(YumUtilBase): + if hasattr(rpm, 'reloadConfig'): + self.optparser.add_option("--target", + help="set target architecture for spec parsing") ++ self.optparser.add_option( ++ "--define", ++ action="append", ++ default=[], ++ metavar="'MACRO EXPR'", ++ help="define the rpm MACRO with value EXPR for spec parsing", ++ ) + self.main() + + def main(self): +@@ -229,11 +236,28 @@ class YumBuildDep(YumUtilBase): + self.logger.info('Getting requirements for %s' % srpm) + self.install_deps(srpm.requiresList(), opts) + ++ # Parse macro defines ++ macros = [] ++ error = False ++ for define in opts.define: ++ words = define.split(None, 1) ++ if len(words) == 1: ++ self.logger.error('Error: No EXPR given for MACRO %%%s' ++ % words[0]) ++ error = True ++ continue ++ macros.append(words) ++ if error: ++ sys.exit(1) ++ + for name in specnames: + # (re)load rpm config for target if set + if reloadworks and opts.target: + rpm.reloadConfig(opts.target) + ++ for macro in macros: ++ rpm.addMacro(*macro) ++ + try: + spec = rpm.spec(name) + except ValueError: diff --git a/SOURCES/BZ-1445751-yum-debug-dump-improve-repo-failure-handling.patch b/SOURCES/BZ-1445751-yum-debug-dump-improve-repo-failure-handling.patch new file mode 100644 index 0000000..67ce20d --- /dev/null +++ b/SOURCES/BZ-1445751-yum-debug-dump-improve-repo-failure-handling.patch @@ -0,0 +1,48 @@ +commit 61232e9f66cc64fffa8517678b6cf224d44b02ef +Author: Michal Domonkos +Date: Wed Jul 12 16:27:53 2017 +0200 + + yum-debug-dump: improve repo failure handling. BZ 1445751 + + Populate the repos prior to iterating over them in dump_repos(). This + fixes the following bugs: + + 1) KeyError when calling returnPackages() on a repo that was previously + disabled by the pkgSack invocation in the same loop due to + skip_if_unavailable=true (BZ 1445751) + + 2) One broken repo with skip_if_unavailable=false would cause all other + (even working) repos in the for loop to report the same error, thus + making the %%%%REPOS section useless + +diff --git a/yum-debug-dump.py b/yum-debug-dump.py +index 67d943f..01ca338 100755 +--- a/yum-debug-dump.py ++++ b/yum-debug-dump.py +@@ -73,6 +73,26 @@ class YumDebugDump(yum.YumBase): + + def dump_repos(self): + msg = "%%%%REPOS\n" ++ ++ # Set up the sacks first, to capture and log any broken repos. We ++ # cannot yet call returnPackages() from this loop as that would lead to ++ # a KeyError if some repo got disabled by pkgSack due to ++ # skip_if_unavailable=true in a previous iteration. ++ # ++ # A failure means remaining repos were not processed, so we have to ++ # retry the whole process ourselves by calling pkgSack again. Since ++ # the worst case scenario is that all the repos are broken, we have to ++ # do this at least as many times as there are enabled repos. ++ for repo in sorted(self.repos.listEnabled()): ++ try: ++ self.pkgSack ++ except Errors.RepoError, e: ++ msg += "Error accessing repo %s: %s\n" % (e.repo, str(e)) ++ self.repos.disableRepo(e.repo.id) ++ else: ++ break ++ ++ # Dump the packages now + for repo in sorted(self.repos.listEnabled()): + try: + msg += '%%%s - %s\n' % (repo.id, repo.urls[0]) diff --git a/SOURCES/BZ-1455318-package-cleanup-dont-remove-required.patch b/SOURCES/BZ-1455318-package-cleanup-dont-remove-required.patch new file mode 100644 index 0000000..2bf732c --- /dev/null +++ b/SOURCES/BZ-1455318-package-cleanup-dont-remove-required.patch @@ -0,0 +1,199 @@ +commit f84a2dbcc28312105246fac51771481640759da5 +Author: Phil Dibowitz +Date: Thu Jul 2 11:40:55 2015 -0700 + + Add option to remove newest dupes instead of oldest dupes + + Sometimes in a failed transaction you need to remove the newest of the dupes and + not the oldest. This provides that option. + +diff --git a/package-cleanup.py b/package-cleanup.py +index acad9f2..13cfb89 100755 +--- a/package-cleanup.py ++++ b/package-cleanup.py +@@ -79,6 +79,9 @@ class PackageCleanup(YumUtilBase): + dupegrp.add_option("--cleandupes", default=False, + dest="cleandupes", action="store_true", + help='Scan for duplicates in your rpmdb and remove older ') ++ dupegrp.add_option("--removenewestdupes", default=False, ++ dest="removenewestdupes", action="store_true", ++ help='Remove the newest dupes instead of the oldest dupes.') + dupegrp.add_option("--noscripts", default=False, + dest="noscripts", action="store_true", + help="disable rpm scriptlets from running when cleaning duplicates") +@@ -172,7 +175,7 @@ class PackageCleanup(YumUtilBase): + + return results + +- def _remove_old_dupes(self): ++ def _remove_dupes(self, newest=False): + """add older duplicate pkgs to be removed in the transaction""" + dupedict = self._find_installed_duplicates() + +@@ -180,7 +183,11 @@ class PackageCleanup(YumUtilBase): + for (name,dupelists) in dupedict.items(): + for dupelist in dupelists: + dupelist.sort() +- for lowpo in dupelist[0:-1]: ++ if newest: ++ plist = dupelist[1:] ++ else: ++ plist = dupelist[0:-1] ++ for lowpo in plist: + removedupes.append(lowpo) + + for po in removedupes: +@@ -373,7 +380,7 @@ class PackageCleanup(YumUtilBase): + sys.exit(1) + if opts.noscripts: + self.conf.tsflags.append('noscripts') +- self._remove_old_dupes() ++ self._remove_dupes(opts.removenewestdupes) + self.run_with_package_names.add('yum-utils') + + if hasattr(self, 'doUtilBuildTransaction'): +commit 27784822a342debd3ecfa04686a35f2e7e576023 +Author: Michal Domonkos +Date: Wed Oct 11 19:26:38 2017 +0200 + + package-cleanup: don't remove required dupes. BZ 1455318 + + Note: Turning removedupes into a set for O(1) complexity on + removedupes.remove(). + +diff --git a/package-cleanup.py b/package-cleanup.py +index 13cfb89..9f74609 100755 +--- a/package-cleanup.py ++++ b/package-cleanup.py +@@ -176,10 +176,12 @@ class PackageCleanup(YumUtilBase): + return results + + def _remove_dupes(self, newest=False): +- """add older duplicate pkgs to be removed in the transaction""" +- dupedict = self._find_installed_duplicates() ++ """add duplicate pkgs to be removed in the transaction, ++ return a dict of excluded dupes and their requiring packages""" + +- removedupes = [] ++ # Find dupes ++ dupedict = self._find_installed_duplicates() ++ removedupes = set() + for (name,dupelists) in dupedict.items(): + for dupelist in dupelists: + dupelist.sort() +@@ -188,11 +190,37 @@ class PackageCleanup(YumUtilBase): + else: + plist = dupelist[0:-1] + for lowpo in plist: +- removedupes.append(lowpo) +- ++ removedupes.add(lowpo) ++ ++ # Exclude any such dupes that would pull other installed packages into ++ # the removal transaction (to prevent us from accidentally removing a ++ # huge part of a working system) by performing a dry transaction(s) ++ # first. ++ excluded = {} ++ while True: ++ for po in removedupes: ++ self.remove(po) ++ changed = False ++ for txmbr in self.tsInfo.getMembers(): ++ requiredby = self._checkRemove(txmbr) ++ if requiredby: ++ removedupes.remove(txmbr.po) ++ excluded[txmbr.po] = requiredby ++ # Do another round, to cover any transitive deps within ++ # removedupes, for example: if foo requires bar requires ++ # baz and removedupes contains bar and baz, then ++ # _checkRemove(baz) won't return bar. ++ changed = True ++ del self.tsInfo ++ if not changed: ++ break ++ ++ # Mark the dupes for removal + for po in removedupes: + self.remove(po) + ++ return excluded ++ + + def _should_show_leaf(self, po, leaf_regex, exclude_devel, exclude_bin): + """ +@@ -380,7 +408,13 @@ class PackageCleanup(YumUtilBase): + sys.exit(1) + if opts.noscripts: + self.conf.tsflags.append('noscripts') +- self._remove_dupes(opts.removenewestdupes) ++ excluded = self._remove_dupes(opts.removenewestdupes) ++ for po, requiredby in excluded.iteritems(): ++ count = len(requiredby) ++ print ('Not removing %s because it is required by %s ' ++ 'installed package%s' % ++ (po.hdr.sprintf(opts.qf), count, ++ 's' if count > 1 else '')) + self.run_with_package_names.add('yum-utils') + + if hasattr(self, 'doUtilBuildTransaction'): +@@ -397,9 +431,20 @@ class PackageCleanup(YumUtilBase): + + if len(self.tsInfo) < 1: + print 'No duplicates to remove' +- sys.exit(0) +- +- sys.exit(self.doUtilTransaction()) ++ errc = 0 ++ else: ++ errc = self.doUtilTransaction() ++ ++ if excluded: ++ self.logger.warn( ++ 'Warning: Some duplicates were not removed because they ' ++ 'are required by installed packages.\n' ++ 'You can try --cleandupes with%s --removenewestdupes, ' ++ 'or review them with --dupes and remove manually.' % ++ ('out' if opts.removenewestdupes else '') ++ ) ++ ++ sys.exit(errc) + + + if __name__ == '__main__': +commit 4594bbc623b68bea6522047fb6267069c8ad94c8 +Author: Michal Domonkos +Date: Wed Oct 11 20:23:06 2017 +0200 + + package-cleanup: update man page + + Add missing options from --help and also clear up the wording of + --removenewestdupes. + +diff --git a/docs/package-cleanup.1 b/docs/package-cleanup.1 +index 61959ac..5b7e1c0 100644 +--- a/docs/package-cleanup.1 ++++ b/docs/package-cleanup.1 +@@ -36,6 +36,10 @@ Scan for duplicates in the local RPM database. + .IP "\fB\-\-cleandupes\fP" + Scan for duplicates in the local RPM database and clean out the + older versions. ++.IP "\fB\-\-removenewestdupes\fP" ++Remove the newest dupes instead of the oldest dupes when cleaning duplicates. ++.IP "\fB\-\-noscripts\fP" ++Disable rpm scriptlets from running when cleaning duplicates. + .IP "\fB\-\-count \fP" + Number of duplicate/kernel packages to keep on the system (default 2) + .PP +diff --git a/package-cleanup.py b/package-cleanup.py +index 9f74609..4a44326 100755 +--- a/package-cleanup.py ++++ b/package-cleanup.py +@@ -81,7 +81,7 @@ class PackageCleanup(YumUtilBase): + help='Scan for duplicates in your rpmdb and remove older ') + dupegrp.add_option("--removenewestdupes", default=False, + dest="removenewestdupes", action="store_true", +- help='Remove the newest dupes instead of the oldest dupes.') ++ help='Remove the newest dupes instead of the oldest dupes when cleaning duplicates.') + dupegrp.add_option("--noscripts", default=False, + dest="noscripts", action="store_true", + help="disable rpm scriptlets from running when cleaning duplicates") diff --git a/SOURCES/BZ-1458098-yumdownloader-crash-broken-metadata.patch b/SOURCES/BZ-1458098-yumdownloader-crash-broken-metadata.patch new file mode 100644 index 0000000..ab69980 --- /dev/null +++ b/SOURCES/BZ-1458098-yumdownloader-crash-broken-metadata.patch @@ -0,0 +1,21 @@ +commit 6fa187521c370a3b13503ee330140778d1dbafc1 +Author: Valentina Mukhamedzhanova +Date: Fri Oct 20 13:33:11 2017 +0200 + + yumdownloader: fix crash on broken srpm metadata. + +diff --git a/yumdownloader.py b/yumdownloader.py +index 1b95e8d..a0db95c 100755 +--- a/yumdownloader.py ++++ b/yumdownloader.py +@@ -47,6 +47,10 @@ def _best_convert_pkg2srcpkgs(self, opts, pkg): + if not opts.source or pkg.arch == 'src': + return [pkg] + ++ if pkg.sourcerpm is None: ++ self.logger.error('No source RPM found for %s' % str(pkg)) ++ return [] ++ + (n,v,r,e,a) = rpmUtils.miscutils.splitFilename(pkg.sourcerpm) + src = self.pkgSack.searchNevra(name=n, ver=v, rel=r, arch='src') + if src == []: diff --git a/SOURCES/BZ-1470647-add-pre-transaction-actions-plugin.patch b/SOURCES/BZ-1470647-add-pre-transaction-actions-plugin.patch new file mode 100644 index 0000000..9059dc8 --- /dev/null +++ b/SOURCES/BZ-1470647-add-pre-transaction-actions-plugin.patch @@ -0,0 +1,200 @@ +diff -up yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.conf.orig yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.conf +--- yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.conf.orig 2017-10-27 17:30:16.579550073 +0200 ++++ yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.conf 2017-10-27 17:30:16.579550073 +0200 +@@ -0,0 +1,3 @@ ++[main] ++enabled = 1 ++actiondir = /etc/yum/pre-actions/ +diff -up yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py.orig yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py +--- yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py.orig 2017-10-27 17:30:16.579550073 +0200 ++++ yum-utils-1.1.31/plugins/pre-transaction-actions/pre-transaction-actions.py 2017-10-27 17:30:16.579550073 +0200 +@@ -0,0 +1,164 @@ ++# 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 ++ ++""" ++This plugin runs actions prior to the transaction based on the content of the ++transaction. ++""" ++ ++ ++from yum.plugins import TYPE_CORE ++from yum.constants import * ++import yum.misc ++from yum.parser import varReplace ++from yum.packages import parsePackages ++import fnmatch ++import re ++import os ++import glob ++import shlex ++ ++requires_api_version = '2.4' ++plugin_type = (TYPE_CORE,) ++ ++def parse_actions(ddir, conduit): ++ """read in .action files from ddir path. ++ store content in a list of tuples""" ++ action_tuples = [] # (action key, action_state, shell command) ++ action_file_list = [] ++ if os.access(ddir, os.R_OK): ++ action_file_list.extend(glob.glob(ddir + "*.action")) ++ ++ if action_file_list: ++ for f in action_file_list: ++ for line in open(f).readlines(): ++ line = line.strip() ++ if line and line[0] != "#": ++ try: ++ (a_key, a_state, a_command) = line.split(':', 2) ++ except ValueError,e: ++ conduit.error(2,'Bad Action Line: %s' % line) ++ continue ++ else: ++ action_tuples.append((a_key, a_state, a_command)) ++ ++ return action_tuples ++ ++def _convert_vars(txmbr, command): ++ """converts %options on the command to their values from the package it ++ is running it for: takes $name, $arch, $ver, $rel, $epoch, ++ $state, $repoid""" ++ state_dict = { TS_INSTALL: 'install', ++ TS_TRUEINSTALL: 'install', ++ TS_OBSOLETING: 'obsoleting', ++ TS_UPDATE: 'updating', ++ TS_ERASE: 'remove', ++ TS_OBSOLETED: 'obsoleted', ++ TS_UPDATED: 'updated'} ++ try: ++ state = state_dict[txmbr.output_state] ++ except KeyError: ++ state = 'unknown - %s' % txmbr.output_state ++ ++ vardict = {'name': txmbr.name, ++ 'arch': txmbr.arch, ++ 'ver': txmbr.version, ++ 'rel': txmbr.release, ++ 'epoch': txmbr.epoch, ++ 'repoid': txmbr.repoid, ++ 'state': state } ++ ++ result = varReplace(command, vardict) ++ return result ++ ++ ++def pretrans_hook(conduit): ++ # we have provides/requires for everything ++ # we do not have filelists for erasures ++ # we have to fetch filelists for the package object for installs/updates ++ action_dir = conduit.confString('main','actiondir','/etc/yum/pre-actions/') ++ action_tuples = parse_actions(action_dir, conduit) ++ commands_to_run = {} ++ ts = conduit.getTsInfo() ++ all = ts.getMembers() ++ removes = ts.getMembersWithState(output_states=TS_REMOVE_STATES) ++ installs = ts.getMembersWithState(output_states=TS_INSTALL_STATES) ++ updates = ts.getMembersWithState(output_states=[TS_UPDATE, TS_OBSOLETING]) ++ ++ for (a_k, a_s, a_c) in action_tuples: ++ #print 'if %s in state %s the run %s' %( a_k, a_s, a_c) ++ if a_s == 'update': ++ pkgset = updates ++ elif a_s == 'install': ++ pkgset = installs ++ elif a_s == 'remove': ++ pkgset = removes ++ elif a_s == 'any': ++ pkgset = all ++ else: ++ # no idea what this is skip it ++ conduit.error(2,'whaa? %s' % a_s) ++ continue ++ ++ if a_k.startswith('/'): ++ if yum.misc.re_glob(a_k): ++ restring = fnmatch.translate(a_k) ++ c_string = re.compile(restring) ++ ++ for txmbr in pkgset: ++ matched = False ++ thispo = txmbr.po ++ ++ if not yum.misc.re_glob(a_k): ++ if a_k in thispo.filelist + thispo.dirlist + thispo.ghostlist: ++ thiscommand = _convert_vars(txmbr, a_c) ++ commands_to_run[thiscommand] = 1 ++ matched = True ++ else: ++ for name in thispo.filelist + thispo.dirlist + thispo.ghostlist: ++ if c_string.match(name): ++ thiscommand = _convert_vars(txmbr, a_c) ++ commands_to_run[thiscommand] = 1 ++ matched = True ++ break ++ ++ if matched: ++ break ++ continue ++ ++ if a_k.find('/') == -1: # pkgspec ++ pkgs = [ txmbr.po for txmbr in pkgset ] ++ e,m,u = parsePackages(pkgs, [a_k]) ++ if not u: ++ for pkg in e+m: ++ for txmbr in ts.getMembers(pkgtup=pkg.pkgtup): ++ thiscommand = _convert_vars(txmbr, a_c) ++ commands_to_run[thiscommand] = 1 ++ continue ++ ++ for comm in commands_to_run.keys(): ++ try: ++ args = shlex.split(comm) ++ except ValueError, e: ++ conduit.error(2,"command was not parseable: %s" % comm) ++ continue ++ #try ++ conduit.info(2,'Running pre transaction command: %s' % comm) ++ p = os.system(comm) ++ #except? ++ ++ +diff -up yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action.orig yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action +--- yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action.orig 2017-10-27 17:30:16.579550073 +0200 ++++ yum-utils-1.1.31/plugins/pre-transaction-actions/sample.action 2017-10-27 17:30:16.579550073 +0200 +@@ -0,0 +1,21 @@ ++#action_key:transaction_state:command ++# action_key can be: pkgglob, /path/to/file (wildcards allowed) ++# transaction_state can be: install,update,remove,any ++# command can be: any shell command ++# the following variables are allowed to be passed to any command: ++# $name - package name ++# $arch - package arch ++# $ver - package version ++# $rel - package release ++# $epoch - package epoch ++# $repoid - package repository id ++# $state - text string of state of the package in the transaction set ++# ++# file matches cannot be used with removes b/c we don't have the info available ++ ++*:install:touch /tmp/$name-installed ++zsh:remove:touch /tmp/zsh-removed ++zsh:install:touch /tmp/zsh-installed-also ++/bin/z*h:install:touch /tmp/bin-zsh-installed ++z*h:any:touch /tmp/bin-zsh-any ++ diff --git a/SPECS/yum-utils.spec b/SPECS/yum-utils.spec index 52d2722..0d479fc 100644 --- a/SPECS/yum-utils.spec +++ b/SPECS/yum-utils.spec @@ -12,7 +12,7 @@ Summary: Utilities based around the yum package manager Name: yum-utils Version: 1.1.31 -Release: 42%{?dist} +Release: 45%{?dist} License: GPLv2+ Group: Development/Tools Source: http://yum.baseurl.org/download/yum-utils/%{name}-%{version}.tar.gz @@ -62,6 +62,17 @@ Patch150: BZ-1403015-yum-config-manager-select-disabled-repoid-setopts.patch Patch151: BZ-1406891-verify-exit-status.patch Patch152: BZ-1429831-yum-copr.patch +#rhel-7.5 +Patch160: BZ-1458098-yumdownloader-crash-broken-metadata.patch +Patch161: BZ-1455318-package-cleanup-dont-remove-required.patch +Patch162: BZ-1428210-fastestmirror-use-prereposetup.patch +Patch163: BZ-1445751-yum-debug-dump-improve-repo-failure-handling.patch +Patch164: BZ-1470647-add-pre-transaction-actions-plugin.patch +Patch165: BZ-1437636-yum-builddep-add-define-opt.patch +Patch166: BZ-1349433-verifytree-handle-no-core-group.patch +Patch167: BZ-1333353-verifytree-fix-handling-no-comps.patch +Patch168: BZ-1127783-transaction-actions-fix-file-globs.patch + URL: http://yum.baseurl.org/download/yum-utils/ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildArch: noarch @@ -309,6 +320,16 @@ This plugin removes any unused dependencies that were brought in by an install but would not normally be removed. It helps to keep a system clean of unused libraries and packages. +%package -n yum-plugin-pre-transaction-actions +Summary: Yum plugin to run arbitrary commands when certain pkgs are acted on +Group: System Environment/Base +Provides: yum-pre-transaction-actions = %{version}-%{release} +Requires: yum >= 3.2.19 + +%description -n yum-plugin-pre-transaction-actions +This plugin allows the user to run arbitrary actions prior to a transaction +when specified packages are changed. + %package -n yum-plugin-post-transaction-actions Summary: Yum plugin to run arbitrary commands when certain pkgs are acted on Group: System Environment/Base @@ -480,6 +501,17 @@ This plugin touches rpmdb files to work around overlayfs issues. %patch151 -p1 %patch152 -p1 +#rhel-7.5 +%patch160 -p1 +%patch161 -p1 +%patch162 -p1 +%patch163 -p1 +%patch164 -p1 +%patch165 -p1 +%patch166 -p1 +%patch167 -p1 +%patch168 -p1 + %install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install @@ -504,6 +536,7 @@ plugins="\ verify \ keys \ remove-with-leaves \ + pre-transaction-actions \ post-transaction-actions \ rpm-warm-cache \ auto-update-debuginfo \ @@ -527,6 +560,7 @@ plugins="$plugins \ %endif mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/yum/pluginconf.d/ $RPM_BUILD_ROOT/%pluginhome +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/yum/pre-actions mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/yum/post-actions cd plugins @@ -728,6 +762,15 @@ fi %{pluginhome}/remove-with-leaves.* %config(noreplace) %{_sysconfdir}/yum/pluginconf.d/remove-with-leaves.conf +%files -n yum-plugin-pre-transaction-actions +%defattr(-, root, root) +%doc COPYING +%{pluginhome}/pre-transaction-actions.* +%config(noreplace) %{_sysconfdir}/yum/pluginconf.d/pre-transaction-actions.conf +%doc plugins/pre-transaction-actions/sample.action +# Default *.action file dropping dir. +%dir %{_sysconfdir}/yum/pre-actions + %files -n yum-plugin-post-transaction-actions %defattr(-, root, root) %doc COPYING @@ -799,6 +842,30 @@ fi %{_mandir}/man1/yum-ovl.1.* %changelog +* Tue Nov 21 2017 Valentina Mukhamedzhanova - 1.1.31-45 +- Fix file globbing in transaction-actions. +- Related: bug#1470647 + +* Mon Oct 30 2017 Valentina Mukhamedzhanova - 1.1.31-44 +- Add pre-transaction-actions plugin. +- Resolves: bug#1470647 +- yum-builddep: add --define option. +- Resolves: bug#1437636 +- verifytree: handle no @core group gracefully. +- Resolves: bug#1349433 +- verifytree: fix handling of missing comps. +- Resolves: bug#1333353 + +* Fri Oct 20 2017 Valentina Mukhamedzhanova - 1.1.31-43 +- yumdownloader: fix crash on broken srpm metadata. +- Resolves: bug#1458098 +- package-cleanup: don't remove required dupes. +- Resolves: bug#1455318 +- fastestmirror: move the logic before MD retrieval. +- Resolves: bug#1428210 +- yum-debug-dump: improve repo failure handling. +- Resolves: bug#1445751 + * Tue Mar 21 2017 Valentina Mukhamedzhanova - 1.1.31-42 - Add yum-plugin-copr. - Resolves: bug#1429831