From 4764048a3feaf257f63d1a63cd86f57591002776 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jan 16 2021 08:10:51 +0000 Subject: import dnf-4.4.2-3.el8 --- diff --git a/SOURCES/0003-Post-transaction-summary-is-logged-for-API-users-RhBug-1855158.patch b/SOURCES/0003-Post-transaction-summary-is-logged-for-API-users-RhBug-1855158.patch new file mode 100644 index 0000000..d34928f --- /dev/null +++ b/SOURCES/0003-Post-transaction-summary-is-logged-for-API-users-RhBug-1855158.patch @@ -0,0 +1,567 @@ +From 9ed390d08a9f2b66f4e352532fa526fc64e329d4 Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Tue, 28 Jul 2020 09:50:10 +0200 +Subject: [PATCH 1/3] Remove unused loops attribute from + DepSolveProgressCallBack + +--- + dnf/cli/output.py | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/dnf/cli/output.py b/dnf/cli/output.py +index de188ffbd1..44d5f8b89f 100644 +--- a/dnf/cli/output.py ++++ b/dnf/cli/output.py +@@ -1987,10 +1987,6 @@ def historyInfoCmdPkgsAltered(self, old, pats=[]): + class DepSolveProgressCallBack(dnf.callback.Depsolve): + """Provides text output callback functions for Dependency Solver callback.""" + +- def __init__(self): +- """requires yum-cli log and errorlog functions as arguments""" +- self.loops = 0 +- + def pkg_added(self, pkg, mode): + """Print information about a package being added to the + transaction set. +@@ -2037,7 +2033,6 @@ def start(self): + process. + """ + logger.debug(_('--> Starting dependency resolution')) +- self.loops += 1 + + def end(self): + """Output a message stating that dependency resolution has finished.""" + +From 0ee646f4965c597f2832ed3df9d9f0e6546dcc54 Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Wed, 21 Oct 2020 11:47:43 +0200 +Subject: [PATCH 2/3] Remove unused parameter of _make_lists() + +--- + dnf/cli/output.py | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/dnf/cli/output.py b/dnf/cli/output.py +index 44d5f8b89f..af8a968770 100644 +--- a/dnf/cli/output.py ++++ b/dnf/cli/output.py +@@ -52,7 +52,8 @@ + + logger = logging.getLogger('dnf') + +-def _make_lists(transaction, goal): ++ ++def _make_lists(transaction): + b = dnf.util.Bunch({ + 'downgraded': [], + 'erased': [], +@@ -1101,7 +1102,7 @@ def list_transaction(self, transaction, total_width=None): + # in order to display module changes when RPM transaction is empty + transaction = [] + +- list_bunch = _make_lists(transaction, self.base._goal) ++ list_bunch = _make_lists(transaction) + pkglist_lines = [] + data = {'n' : {}, 'v' : {}, 'r' : {}} + a_wid = 0 # Arch can't get "that big" ... so always use the max. +@@ -1488,7 +1489,7 @@ def _tsi_or_pkg_nevra_cmp(item1, item2): + return (item1.arch > item2.arch) - (item1.arch < item2.arch) + + out = '' +- list_bunch = _make_lists(transaction, self.base._goal) ++ list_bunch = _make_lists(transaction) + + skipped_conflicts, skipped_broken = self._skipped_packages( + report_problems=False, transaction=transaction) + +From 865b7183453684de6a25e77fddf5a2d11fbffba8 Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Wed, 21 Oct 2020 17:59:46 +0200 +Subject: [PATCH 3/3] Post transaction summary is logged for API users + (RhBug:1855158) + +Post transaction summary is always logged into /var/log/dnf.log. +When transaction is called from cli, the summary is also printed to +stdout in columns (as previously). + += changelog = +msg: Packages installed/removed via DNF API are logged into dnf.log +type: enhancement +resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1855158 +--- + dnf/base.py | 46 ++++++++++++- + dnf/cli/cli.py | 8 ++- + dnf/cli/output.py | 167 ++++++++-------------------------------------- + dnf/util.py | 102 +++++++++++++++++++++++++++- + 4 files changed, 177 insertions(+), 146 deletions(-) + +diff --git a/dnf/base.py b/dnf/base.py +index 075e74265a..c0d7712605 100644 +--- a/dnf/base.py ++++ b/dnf/base.py +@@ -28,12 +28,12 @@ + import dnf + import libdnf.transaction + ++from copy import deepcopy + from dnf.comps import CompsQuery + from dnf.i18n import _, P_, ucd + from dnf.util import _parse_specs + from dnf.db.history import SwdbInterface + from dnf.yum import misc +-from functools import reduce + try: + from collections.abc import Sequence + except ImportError: +@@ -549,7 +549,7 @@ def _ts(self): + if self.conf.ignorearch: + self._rpm_probfilter.add(rpm.RPMPROB_FILTER_IGNOREARCH) + +- probfilter = reduce(operator.or_, self._rpm_probfilter, 0) ++ probfilter = functools.reduce(operator.or_, self._rpm_probfilter, 0) + self._priv_ts.setProbFilter(probfilter) + return self._priv_ts + +@@ -890,6 +890,15 @@ def do_transaction(self, display=()): + self._plugins.unload_removed_plugins(self.transaction) + self._plugins.run_transaction() + ++ # log post transaction summary ++ def _pto_callback(action, tsis): ++ msgs = [] ++ for tsi in tsis: ++ msgs.append('{}: {}'.format(action, str(tsi))) ++ return msgs ++ for msg in dnf.util._post_transaction_output(self, self.transaction, _pto_callback): ++ logger.debug(msg) ++ + return tid + + def _trans_error_summary(self, errstring): +@@ -1311,7 +1320,7 @@ def _do_package_lists(self, pkgnarrow='all', patterns=None, showdups=None, + if patterns is None or len(patterns) == 0: + return list_fn(None) + yghs = map(list_fn, patterns) +- return reduce(lambda a, b: a.merge_lists(b), yghs) ++ return functools.reduce(lambda a, b: a.merge_lists(b), yghs) + + def _list_pattern(self, pkgnarrow, pattern, showdups, ignore_case, + reponame=None): +@@ -2579,6 +2588,37 @@ def setup_loggers(self): + """ + self._logging._setup_from_dnf_conf(self.conf, file_loggers_only=True) + ++ def _skipped_packages(self, report_problems, transaction): ++ """returns set of conflicting packages and set of packages with broken dependency that would ++ be additionally installed when --best and --allowerasing""" ++ if self._goal.actions & (hawkey.INSTALL | hawkey.UPGRADE | hawkey.UPGRADE_ALL): ++ best = True ++ else: ++ best = False ++ ng = deepcopy(self._goal) ++ params = {"allow_uninstall": self._allow_erasing, ++ "force_best": best, ++ "ignore_weak": True} ++ ret = ng.run(**params) ++ if not ret and report_problems: ++ msg = dnf.util._format_resolve_problems(ng.problem_rules()) ++ logger.warning(msg) ++ problem_conflicts = set(ng.problem_conflicts(available=True)) ++ problem_dependency = set(ng.problem_broken_dependency(available=True)) - problem_conflicts ++ ++ def _nevra(item): ++ return hawkey.NEVRA(name=item.name, epoch=item.epoch, version=item.version, ++ release=item.release, arch=item.arch) ++ ++ # Sometimes, pkg is not in transaction item, therefore, comparing by nevra ++ transaction_nevras = [_nevra(tsi) for tsi in transaction] ++ skipped_conflicts = set( ++ [pkg for pkg in problem_conflicts if _nevra(pkg) not in transaction_nevras]) ++ skipped_dependency = set( ++ [pkg for pkg in problem_dependency if _nevra(pkg) not in transaction_nevras]) ++ ++ return skipped_conflicts, skipped_dependency ++ + + def _msg_installed(pkg): + name = ucd(pkg) +diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py +index 0bc2c119d0..334000362c 100644 +--- a/dnf/cli/cli.py ++++ b/dnf/cli/cli.py +@@ -252,8 +252,12 @@ def do_transaction(self, display=()): + trans = None + + if trans: +- msg = self.output.post_transaction_output(trans) +- logger.info(msg) ++ # the post transaction summary is already written to log during ++ # Base.do_transaction() so here only print the messages to the ++ # user arranged in columns ++ print() ++ print('\n'.join(self.output.post_transaction_output(trans))) ++ print() + for tsi in trans: + if tsi.state == libdnf.transaction.TransactionItemState_ERROR: + raise dnf.exceptions.Error(_('Transaction failed')) +diff --git a/dnf/cli/output.py b/dnf/cli/output.py +index af8a968770..6d729b63ba 100644 +--- a/dnf/cli/output.py ++++ b/dnf/cli/output.py +@@ -21,9 +21,7 @@ + from __future__ import print_function + from __future__ import unicode_literals + +-from copy import deepcopy + import fnmatch +-import functools + import hawkey + import itertools + import libdnf.transaction +@@ -53,51 +51,6 @@ + logger = logging.getLogger('dnf') + + +-def _make_lists(transaction): +- b = dnf.util.Bunch({ +- 'downgraded': [], +- 'erased': [], +- 'erased_clean': [], +- 'erased_dep': [], +- 'installed': [], +- 'installed_group': [], +- 'installed_dep': [], +- 'installed_weak': [], +- 'reinstalled': [], +- 'upgraded': [], +- 'failed': [], +- }) +- +- for tsi in transaction: +- if tsi.state == libdnf.transaction.TransactionItemState_ERROR: +- b.failed.append(tsi) +- elif tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADE: +- b.downgraded.append(tsi) +- elif tsi.action == libdnf.transaction.TransactionItemAction_INSTALL: +- if tsi.reason == libdnf.transaction.TransactionItemReason_GROUP: +- b.installed_group.append(tsi) +- elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY: +- b.installed_dep.append(tsi) +- elif tsi.reason == libdnf.transaction.TransactionItemReason_WEAK_DEPENDENCY: +- b.installed_weak.append(tsi) +- else: +- # TransactionItemReason_USER +- b.installed.append(tsi) +- elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALL: +- b.reinstalled.append(tsi) +- elif tsi.action == libdnf.transaction.TransactionItemAction_REMOVE: +- if tsi.reason == libdnf.transaction.TransactionItemReason_CLEAN: +- b.erased_clean.append(tsi) +- elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY: +- b.erased_dep.append(tsi) +- else: +- b.erased.append(tsi) +- elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADE: +- b.upgraded.append(tsi) +- +- return b +- +- + def _spread_in_columns(cols_count, label, lst): + left = itertools.chain((label,), itertools.repeat('')) + lst_length = len(lst) +@@ -1057,37 +1010,6 @@ def list_group_transaction(self, comps, history, diff): + out[0:0] = self._banner(col_data, (_('Group'), _('Packages'), '', '')) + return '\n'.join(out) + +- def _skipped_packages(self, report_problems, transaction): +- """returns set of conflicting packages and set of packages with broken dependency that would +- be additionally installed when --best and --allowerasing""" +- if self.base._goal.actions & (hawkey.INSTALL | hawkey.UPGRADE | hawkey.UPGRADE_ALL): +- best = True +- else: +- best = False +- ng = deepcopy(self.base._goal) +- params = {"allow_uninstall": self.base._allow_erasing, +- "force_best": best, +- "ignore_weak": True} +- ret = ng.run(**params) +- if not ret and report_problems: +- msg = dnf.util._format_resolve_problems(ng.problem_rules()) +- logger.warning(msg) +- problem_conflicts = set(ng.problem_conflicts(available=True)) +- problem_dependency = set(ng.problem_broken_dependency(available=True)) - problem_conflicts +- +- def _nevra(item): +- return hawkey.NEVRA(name=item.name, epoch=item.epoch, version=item.version, +- release=item.release, arch=item.arch) +- +- # Sometimes, pkg is not in transaction item, therefore, comparing by nevra +- transaction_nevras = [_nevra(tsi) for tsi in transaction] +- skipped_conflicts = set( +- [pkg for pkg in problem_conflicts if _nevra(pkg) not in transaction_nevras]) +- skipped_dependency = set( +- [pkg for pkg in problem_dependency if _nevra(pkg) not in transaction_nevras]) +- +- return skipped_conflicts, skipped_dependency +- + def list_transaction(self, transaction, total_width=None): + """Return a string representation of the transaction in an + easy-to-read format. +@@ -1102,7 +1024,7 @@ def list_transaction(self, transaction, total_width=None): + # in order to display module changes when RPM transaction is empty + transaction = [] + +- list_bunch = _make_lists(transaction) ++ list_bunch = dnf.util._make_lists(transaction) + pkglist_lines = [] + data = {'n' : {}, 'v' : {}, 'r' : {}} + a_wid = 0 # Arch can't get "that big" ... so always use the max. +@@ -1271,7 +1193,7 @@ def format_line(group): + # show skipped conflicting packages + if not self.conf.best and self.base._goal.actions & forward_actions: + lines = [] +- skipped_conflicts, skipped_broken = self._skipped_packages( ++ skipped_conflicts, skipped_broken = self.base._skipped_packages( + report_problems=True, transaction=transaction) + skipped_broken = dict((str(pkg), pkg) for pkg in skipped_broken) + for pkg in sorted(skipped_conflicts): +@@ -1436,13 +1358,8 @@ def format_line(group): + max_msg_count, count, msg_pkgs)) + return ''.join(out) + +- def post_transaction_output(self, transaction): +- """Returns a human-readable summary of the results of the +- transaction. + +- :return: a string containing a human-readable summary of the +- results of the transaction +- """ ++ def _pto_callback(self, action, tsis): + # Works a bit like calcColumns, but we never overflow a column we just + # have a dynamic number of columns. + def _fits_in_cols(msgs, num): +@@ -1472,61 +1389,33 @@ def _fits_in_cols(msgs, num): + col_lens[col] *= -1 + return col_lens + +- def _tsi_or_pkg_nevra_cmp(item1, item2): +- """Compares two transaction items or packages by nevra. +- Used as a fallback when tsi does not contain package object. +- """ +- ret = (item1.name > item2.name) - (item1.name < item2.name) +- if ret != 0: +- return ret +- nevra1 = hawkey.NEVRA(name=item1.name, epoch=item1.epoch, version=item1.version, +- release=item1.release, arch=item1.arch) +- nevra2 = hawkey.NEVRA(name=item2.name, epoch=item2.epoch, version=item2.version, +- release=item2.release, arch=item2.arch) +- ret = nevra1.evr_cmp(nevra2, self.sack) +- if ret != 0: +- return ret +- return (item1.arch > item2.arch) - (item1.arch < item2.arch) +- +- out = '' +- list_bunch = _make_lists(transaction) +- +- skipped_conflicts, skipped_broken = self._skipped_packages( +- report_problems=False, transaction=transaction) +- skipped = skipped_conflicts.union(skipped_broken) +- +- for (action, tsis) in [(_('Upgraded'), list_bunch.upgraded), +- (_('Downgraded'), list_bunch.downgraded), +- (_('Installed'), list_bunch.installed + +- list_bunch.installed_group + +- list_bunch.installed_weak + +- list_bunch.installed_dep), +- (_('Reinstalled'), list_bunch.reinstalled), +- (_('Skipped'), skipped), +- (_('Removed'), list_bunch.erased + +- list_bunch.erased_dep + +- list_bunch.erased_clean), +- (_('Failed'), list_bunch.failed)]: +- if not tsis: +- continue +- msgs = [] +- out += '\n%s:\n' % action +- for tsi in sorted(tsis, key=functools.cmp_to_key(_tsi_or_pkg_nevra_cmp)): +- msgs.append(str(tsi)) +- for num in (8, 7, 6, 5, 4, 3, 2): +- cols = _fits_in_cols(msgs, num) +- if cols: +- break +- if not cols: +- cols = [-(self.term.columns - 2)] +- while msgs: +- current_msgs = msgs[:len(cols)] +- out += ' ' +- out += self.fmtColumns(zip(current_msgs, cols), end=u'\n') +- msgs = msgs[len(cols):] +- ++ if not tsis: ++ return '' ++ out = [] ++ msgs = [] ++ out.append('{}:'.format(action)) ++ for tsi in tsis: ++ msgs.append(str(tsi)) ++ for num in (8, 7, 6, 5, 4, 3, 2): ++ cols = _fits_in_cols(msgs, num) ++ if cols: ++ break ++ if not cols: ++ cols = [-(self.term.columns - 2)] ++ while msgs: ++ current_msgs = msgs[:len(cols)] ++ out.append(' {}'.format(self.fmtColumns(zip(current_msgs, cols)))) ++ msgs = msgs[len(cols):] + return out + ++ ++ def post_transaction_output(self, transaction): ++ """ ++ Return a human-readable summary of the transaction. Packages in sections ++ are arranged to columns. ++ """ ++ return dnf.util._post_transaction_output(self.base, transaction, self._pto_callback) ++ + def setup_progress_callbacks(self): + """Set up the progress callbacks and various + output bars based on debug level. +diff --git a/dnf/util.py b/dnf/util.py +index 8cf362706d..0beb04424d 100644 +--- a/dnf/util.py ++++ b/dnf/util.py +@@ -24,13 +24,14 @@ + + from .pycomp import PY3, basestring + from dnf.i18n import _, ucd +-from functools import reduce + import argparse + import dnf + import dnf.callback + import dnf.const + import dnf.pycomp + import errno ++import functools ++import hawkey + import itertools + import locale + import logging +@@ -41,6 +42,7 @@ + import tempfile + import time + import libdnf.repo ++import libdnf.transaction + + logger = logging.getLogger('dnf') + +@@ -195,7 +197,7 @@ def group_by_filter(fn, iterable): + def splitter(acc, item): + acc[not bool(fn(item))].append(item) + return acc +- return reduce(splitter, iterable, ([], [])) ++ return functools.reduce(splitter, iterable, ([], [])) + + def insert_if(item, iterable, condition): + """Insert an item into an iterable by a condition.""" +@@ -504,3 +506,99 @@ def __setattr__(self, what, val): + def setter(item): + setattr(item, what, val) + return list(map(setter, self)) ++ ++ ++def _make_lists(transaction): ++ b = Bunch({ ++ 'downgraded': [], ++ 'erased': [], ++ 'erased_clean': [], ++ 'erased_dep': [], ++ 'installed': [], ++ 'installed_group': [], ++ 'installed_dep': [], ++ 'installed_weak': [], ++ 'reinstalled': [], ++ 'upgraded': [], ++ 'failed': [], ++ }) ++ ++ for tsi in transaction: ++ if tsi.state == libdnf.transaction.TransactionItemState_ERROR: ++ b.failed.append(tsi) ++ elif tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADE: ++ b.downgraded.append(tsi) ++ elif tsi.action == libdnf.transaction.TransactionItemAction_INSTALL: ++ if tsi.reason == libdnf.transaction.TransactionItemReason_GROUP: ++ b.installed_group.append(tsi) ++ elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY: ++ b.installed_dep.append(tsi) ++ elif tsi.reason == libdnf.transaction.TransactionItemReason_WEAK_DEPENDENCY: ++ b.installed_weak.append(tsi) ++ else: ++ # TransactionItemReason_USER ++ b.installed.append(tsi) ++ elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALL: ++ b.reinstalled.append(tsi) ++ elif tsi.action == libdnf.transaction.TransactionItemAction_REMOVE: ++ if tsi.reason == libdnf.transaction.TransactionItemReason_CLEAN: ++ b.erased_clean.append(tsi) ++ elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY: ++ b.erased_dep.append(tsi) ++ else: ++ b.erased.append(tsi) ++ elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADE: ++ b.upgraded.append(tsi) ++ ++ return b ++ ++ ++def _post_transaction_output(base, transaction, action_callback): ++ """Returns a human-readable summary of the results of the ++ transaction. ++ ++ :param action_callback: function generating output for specific action. It ++ takes two parameters - action as a string and list of affected packages for ++ this action ++ :return: a list of lines containing a human-readable summary of the ++ results of the transaction ++ """ ++ def _tsi_or_pkg_nevra_cmp(item1, item2): ++ """Compares two transaction items or packages by nevra. ++ Used as a fallback when tsi does not contain package object. ++ """ ++ ret = (item1.name > item2.name) - (item1.name < item2.name) ++ if ret != 0: ++ return ret ++ nevra1 = hawkey.NEVRA(name=item1.name, epoch=item1.epoch, version=item1.version, ++ release=item1.release, arch=item1.arch) ++ nevra2 = hawkey.NEVRA(name=item2.name, epoch=item2.epoch, version=item2.version, ++ release=item2.release, arch=item2.arch) ++ ret = nevra1.evr_cmp(nevra2, base.sack) ++ if ret != 0: ++ return ret ++ return (item1.arch > item2.arch) - (item1.arch < item2.arch) ++ ++ list_bunch = dnf.util._make_lists(transaction) ++ ++ skipped_conflicts, skipped_broken = base._skipped_packages( ++ report_problems=False, transaction=transaction) ++ skipped = skipped_conflicts.union(skipped_broken) ++ ++ out = [] ++ for (action, tsis) in [(_('Upgraded'), list_bunch.upgraded), ++ (_('Downgraded'), list_bunch.downgraded), ++ (_('Installed'), list_bunch.installed + ++ list_bunch.installed_group + ++ list_bunch.installed_weak + ++ list_bunch.installed_dep), ++ (_('Reinstalled'), list_bunch.reinstalled), ++ (_('Skipped'), skipped), ++ (_('Removed'), list_bunch.erased + ++ list_bunch.erased_dep + ++ list_bunch.erased_clean), ++ (_('Failed'), list_bunch.failed)]: ++ out.extend(action_callback( ++ action, sorted(tsis, key=functools.cmp_to_key(_tsi_or_pkg_nevra_cmp)))) ++ ++ return out diff --git a/SOURCES/0004-Log-scriptlets-output-also-for-API-users-RhBug-1847340.patch b/SOURCES/0004-Log-scriptlets-output-also-for-API-users-RhBug-1847340.patch new file mode 100644 index 0000000..8447353 --- /dev/null +++ b/SOURCES/0004-Log-scriptlets-output-also-for-API-users-RhBug-1847340.patch @@ -0,0 +1,130 @@ +From df64fd36d7fefe39a96fea3f41e35785bebd37ec Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Wed, 2 Dec 2020 16:33:26 +0100 +Subject: [PATCH 1/2] Log scriptlets output also for API users (RhBug:1847340) + +Messages logged into /var/log/dnf.rpm.log are now the same for both +command line and API usage. + +https://bugzilla.redhat.com/show_bug.cgi?id=1847340 +--- + dnf/cli/output.py | 7 +------ + dnf/yum/rpmtrans.py | 9 ++++++++- + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/dnf/cli/output.py b/dnf/cli/output.py +index 51d6829ca6..86260661fc 100644 +--- a/dnf/cli/output.py ++++ b/dnf/cli/output.py +@@ -2151,12 +2151,7 @@ def error(self, message): + pass + + def scriptout(self, msgs): +- """Print messages originating from a package script. +- +- :param msgs: the messages coming from the script +- """ +- if msgs: +- self.rpm_logger.info(ucd(msgs)) ++ pass + + def _makefmt(self, percent, ts_done, ts_total, progress=True, + pkgname=None, wid1=15): +diff --git a/dnf/yum/rpmtrans.py b/dnf/yum/rpmtrans.py +index 447639a476..d6c549d2ed 100644 +--- a/dnf/yum/rpmtrans.py ++++ b/dnf/yum/rpmtrans.py +@@ -113,7 +113,10 @@ def progress(self, package, action, ti_done, ti_total, ts_done, ts_total): + pass + + def scriptout(self, msgs): +- """msgs is the messages that were output (if any).""" ++ """Hook for reporting an rpm scriptlet output. ++ ++ :param msgs: the scriptlet output ++ """ + pass + + def error(self, message): +@@ -156,6 +159,10 @@ def filelog(self, package, action): + msg = '%s: %s' % (action_str, package) + self.rpm_logger.log(dnf.logging.SUBDEBUG, msg) + ++ def scriptout(self, msgs): ++ if msgs: ++ self.rpm_logger.info(ucd(msgs)) ++ + + class RPMTransaction(object): + def __init__(self, base, test=False, displays=()): + +From ee6ffcf640180b2b08d2db50b4b81d2bdefb1f2f Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Thu, 3 Dec 2020 10:08:09 +0100 +Subject: [PATCH 2/2] Straighten inheritance of *Display classes + +--- + dnf/cli/output.py | 15 +++------------ + dnf/yum/rpmtrans.py | 2 +- + 2 files changed, 4 insertions(+), 13 deletions(-) + +diff --git a/dnf/cli/output.py b/dnf/cli/output.py +index 86260661fc..de188ffbd1 100644 +--- a/dnf/cli/output.py ++++ b/dnf/cli/output.py +@@ -37,7 +37,7 @@ + from dnf.cli.format import format_number, format_time + from dnf.i18n import _, C_, P_, ucd, fill_exact_width, textwrap_fill, exact_width, select_short_long + from dnf.pycomp import xrange, basestring, long, unicode, sys_maxsize +-from dnf.yum.rpmtrans import LoggingTransactionDisplay ++from dnf.yum.rpmtrans import TransactionDisplay + from dnf.db.history import MergedTransactionWrapper + import dnf.base + import dnf.callback +@@ -2071,7 +2071,7 @@ def short_id(id): + return self.output.userconfirm() + + +-class CliTransactionDisplay(LoggingTransactionDisplay): ++class CliTransactionDisplay(TransactionDisplay): + """A YUM specific callback class for RPM operations.""" + + width = property(lambda self: dnf.cli.term._term_width()) +@@ -2093,7 +2093,7 @@ def progress(self, package, action, ti_done, ti_total, ts_done, ts_total): + :param package: the package involved in the event + :param action: the type of action that is taking place. Valid + values are given by +- :func:`rpmtrans.LoggingTransactionDisplay.action.keys()` ++ :func:`rpmtrans.TransactionDisplay.action.keys()` + :param ti_done: a number representing the amount of work + already done in the current transaction + :param ti_total: a number representing the total amount of work +@@ -2144,15 +2144,6 @@ def _out_progress(self, ti_done, ti_total, ts_done, ts_total, + if ti_done == ti_total: + print(" ") + +- def filelog(self, package, action): +- pass +- +- def error(self, message): +- pass +- +- def scriptout(self, msgs): +- pass +- + def _makefmt(self, percent, ts_done, ts_total, progress=True, + pkgname=None, wid1=15): + l = len(str(ts_total)) +diff --git a/dnf/yum/rpmtrans.py b/dnf/yum/rpmtrans.py +index d6c549d2ed..51fa921d3e 100644 +--- a/dnf/yum/rpmtrans.py ++++ b/dnf/yum/rpmtrans.py +@@ -143,7 +143,7 @@ def error(self, message): + dnf.util._terminal_messenger('print', message, sys.stderr) + + +-class LoggingTransactionDisplay(ErrorTransactionDisplay): ++class LoggingTransactionDisplay(TransactionDisplay): + ''' + Base class for a RPMTransaction display callback class + ''' diff --git a/SPECS/dnf.spec b/SPECS/dnf.spec index f8271f4..ad6967f 100644 --- a/SPECS/dnf.spec +++ b/SPECS/dnf.spec @@ -82,7 +82,7 @@ It supports RPMs, modules and comps groups & environments. Name: dnf Version: 4.4.2 -Release: 2%{?dist} +Release: 3%{?dist} Summary: %{pkg_summary} # For a breakdown of the licensing, see PACKAGE-LICENSING License: GPLv2+ and GPLv2 and GPL @@ -92,6 +92,10 @@ Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz Patch1: 0001-tests-SQL-write-a-readonly-folder.patch # https://github.com/rpm-software-management/dnf/commit/c2e4901cec947e5be2e5ff5afa22691841d00bdc Patch2: 0002-Revert-Fix-setopt-cachedir-writing-outside-of-installroot.patch +# https://github.com/rpm-software-management/dnf/pull/1675 +Patch3: 0003-Post-transaction-summary-is-logged-for-API-users-RhBug-1855158.patch +# https://github.com/rpm-software-management/dnf/pull/1698 +Patch4: 0004-Log-scriptlets-output-also-for-API-users-RhBug-1847340.patch BuildArch: noarch BuildRequires: cmake @@ -512,6 +516,11 @@ ln -sr %{buildroot}%{confdir}/vars %{buildroot}%{_sysconfdir}/yum/vars %endif %changelog +* Thu Jan 07 2021 Nicola Sella - 4.4.2-3 +- Backport patches +- Log scriptlets output also for API users (RhBug:1847340) +- Post transaction summary is logged for API users (RhBug:1855158) + * Wed Nov 11 2020 Nicola Sella - 4.4.2-2 - Backport patch Revert "Fix --setopt=cachedir writing outside of installroot"