|
|
4f4af9 |
From 9ed390d08a9f2b66f4e352532fa526fc64e329d4 Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Marek Blaha <mblaha@redhat.com>
|
|
|
4f4af9 |
Date: Tue, 28 Jul 2020 09:50:10 +0200
|
|
|
4f4af9 |
Subject: [PATCH 1/3] Remove unused loops attribute from
|
|
|
4f4af9 |
DepSolveProgressCallBack
|
|
|
4f4af9 |
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
dnf/cli/output.py | 5 -----
|
|
|
4f4af9 |
1 file changed, 5 deletions(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
|
|
|
4f4af9 |
index de188ffbd1..44d5f8b89f 100644
|
|
|
4f4af9 |
--- a/dnf/cli/output.py
|
|
|
4f4af9 |
+++ b/dnf/cli/output.py
|
|
|
4f4af9 |
@@ -1987,10 +1987,6 @@ def historyInfoCmdPkgsAltered(self, old, pats=[]):
|
|
|
4f4af9 |
class DepSolveProgressCallBack(dnf.callback.Depsolve):
|
|
|
4f4af9 |
"""Provides text output callback functions for Dependency Solver callback."""
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- def __init__(self):
|
|
|
4f4af9 |
- """requires yum-cli log and errorlog functions as arguments"""
|
|
|
4f4af9 |
- self.loops = 0
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
def pkg_added(self, pkg, mode):
|
|
|
4f4af9 |
"""Print information about a package being added to the
|
|
|
4f4af9 |
transaction set.
|
|
|
4f4af9 |
@@ -2037,7 +2033,6 @@ def start(self):
|
|
|
4f4af9 |
process.
|
|
|
4f4af9 |
"""
|
|
|
4f4af9 |
logger.debug(_('--> Starting dependency resolution'))
|
|
|
4f4af9 |
- self.loops += 1
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def end(self):
|
|
|
4f4af9 |
"""Output a message stating that dependency resolution has finished."""
|
|
|
4f4af9 |
|
|
|
4f4af9 |
From 0ee646f4965c597f2832ed3df9d9f0e6546dcc54 Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Marek Blaha <mblaha@redhat.com>
|
|
|
4f4af9 |
Date: Wed, 21 Oct 2020 11:47:43 +0200
|
|
|
4f4af9 |
Subject: [PATCH 2/3] Remove unused parameter of _make_lists()
|
|
|
4f4af9 |
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
dnf/cli/output.py | 7 ++++---
|
|
|
4f4af9 |
1 file changed, 4 insertions(+), 3 deletions(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
|
|
|
4f4af9 |
index 44d5f8b89f..af8a968770 100644
|
|
|
4f4af9 |
--- a/dnf/cli/output.py
|
|
|
4f4af9 |
+++ b/dnf/cli/output.py
|
|
|
4f4af9 |
@@ -52,7 +52,8 @@
|
|
|
4f4af9 |
|
|
|
4f4af9 |
logger = logging.getLogger('dnf')
|
|
|
4f4af9 |
|
|
|
4f4af9 |
-def _make_lists(transaction, goal):
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+def _make_lists(transaction):
|
|
|
4f4af9 |
b = dnf.util.Bunch({
|
|
|
4f4af9 |
'downgraded': [],
|
|
|
4f4af9 |
'erased': [],
|
|
|
4f4af9 |
@@ -1101,7 +1102,7 @@ def list_transaction(self, transaction, total_width=None):
|
|
|
4f4af9 |
# in order to display module changes when RPM transaction is empty
|
|
|
4f4af9 |
transaction = []
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- list_bunch = _make_lists(transaction, self.base._goal)
|
|
|
4f4af9 |
+ list_bunch = _make_lists(transaction)
|
|
|
4f4af9 |
pkglist_lines = []
|
|
|
4f4af9 |
data = {'n' : {}, 'v' : {}, 'r' : {}}
|
|
|
4f4af9 |
a_wid = 0 # Arch can't get "that big" ... so always use the max.
|
|
|
4f4af9 |
@@ -1488,7 +1489,7 @@ def _tsi_or_pkg_nevra_cmp(item1, item2):
|
|
|
4f4af9 |
return (item1.arch > item2.arch) - (item1.arch < item2.arch)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
out = ''
|
|
|
4f4af9 |
- list_bunch = _make_lists(transaction, self.base._goal)
|
|
|
4f4af9 |
+ list_bunch = _make_lists(transaction)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
skipped_conflicts, skipped_broken = self._skipped_packages(
|
|
|
4f4af9 |
report_problems=False, transaction=transaction)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
From 865b7183453684de6a25e77fddf5a2d11fbffba8 Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Marek Blaha <mblaha@redhat.com>
|
|
|
4f4af9 |
Date: Wed, 21 Oct 2020 17:59:46 +0200
|
|
|
4f4af9 |
Subject: [PATCH 3/3] Post transaction summary is logged for API users
|
|
|
4f4af9 |
(RhBug:1855158)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
Post transaction summary is always logged into /var/log/dnf.log.
|
|
|
4f4af9 |
When transaction is called from cli, the summary is also printed to
|
|
|
4f4af9 |
stdout in columns (as previously).
|
|
|
4f4af9 |
|
|
|
4f4af9 |
= changelog =
|
|
|
4f4af9 |
msg: Packages installed/removed via DNF API are logged into dnf.log
|
|
|
4f4af9 |
type: enhancement
|
|
|
4f4af9 |
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1855158
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
dnf/base.py | 46 ++++++++++++-
|
|
|
4f4af9 |
dnf/cli/cli.py | 8 ++-
|
|
|
4f4af9 |
dnf/cli/output.py | 167 ++++++++--------------------------------------
|
|
|
4f4af9 |
dnf/util.py | 102 +++++++++++++++++++++++++++-
|
|
|
4f4af9 |
4 files changed, 177 insertions(+), 146 deletions(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/base.py b/dnf/base.py
|
|
|
4f4af9 |
index 075e74265a..c0d7712605 100644
|
|
|
4f4af9 |
--- a/dnf/base.py
|
|
|
4f4af9 |
+++ b/dnf/base.py
|
|
|
4f4af9 |
@@ -28,12 +28,12 @@
|
|
|
4f4af9 |
import dnf
|
|
|
4f4af9 |
import libdnf.transaction
|
|
|
4f4af9 |
|
|
|
4f4af9 |
+from copy import deepcopy
|
|
|
4f4af9 |
from dnf.comps import CompsQuery
|
|
|
4f4af9 |
from dnf.i18n import _, P_, ucd
|
|
|
4f4af9 |
from dnf.util import _parse_specs
|
|
|
4f4af9 |
from dnf.db.history import SwdbInterface
|
|
|
4f4af9 |
from dnf.yum import misc
|
|
|
4f4af9 |
-from functools import reduce
|
|
|
4f4af9 |
try:
|
|
|
4f4af9 |
from collections.abc import Sequence
|
|
|
4f4af9 |
except ImportError:
|
|
|
4f4af9 |
@@ -549,7 +549,7 @@ def _ts(self):
|
|
|
4f4af9 |
if self.conf.ignorearch:
|
|
|
4f4af9 |
self._rpm_probfilter.add(rpm.RPMPROB_FILTER_IGNOREARCH)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- probfilter = reduce(operator.or_, self._rpm_probfilter, 0)
|
|
|
4f4af9 |
+ probfilter = functools.reduce(operator.or_, self._rpm_probfilter, 0)
|
|
|
4f4af9 |
self._priv_ts.setProbFilter(probfilter)
|
|
|
4f4af9 |
return self._priv_ts
|
|
|
4f4af9 |
|
|
|
4f4af9 |
@@ -890,6 +890,15 @@ def do_transaction(self, display=()):
|
|
|
4f4af9 |
self._plugins.unload_removed_plugins(self.transaction)
|
|
|
4f4af9 |
self._plugins.run_transaction()
|
|
|
4f4af9 |
|
|
|
4f4af9 |
+ # log post transaction summary
|
|
|
4f4af9 |
+ def _pto_callback(action, tsis):
|
|
|
4f4af9 |
+ msgs = []
|
|
|
4f4af9 |
+ for tsi in tsis:
|
|
|
4f4af9 |
+ msgs.append('{}: {}'.format(action, str(tsi)))
|
|
|
4f4af9 |
+ return msgs
|
|
|
4f4af9 |
+ for msg in dnf.util._post_transaction_output(self, self.transaction, _pto_callback):
|
|
|
4f4af9 |
+ logger.debug(msg)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
return tid
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def _trans_error_summary(self, errstring):
|
|
|
4f4af9 |
@@ -1311,7 +1320,7 @@ def _do_package_lists(self, pkgnarrow='all', patterns=None, showdups=None,
|
|
|
4f4af9 |
if patterns is None or len(patterns) == 0:
|
|
|
4f4af9 |
return list_fn(None)
|
|
|
4f4af9 |
yghs = map(list_fn, patterns)
|
|
|
4f4af9 |
- return reduce(lambda a, b: a.merge_lists(b), yghs)
|
|
|
4f4af9 |
+ return functools.reduce(lambda a, b: a.merge_lists(b), yghs)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def _list_pattern(self, pkgnarrow, pattern, showdups, ignore_case,
|
|
|
4f4af9 |
reponame=None):
|
|
|
4f4af9 |
@@ -2579,6 +2588,37 @@ def setup_loggers(self):
|
|
|
4f4af9 |
"""
|
|
|
4f4af9 |
self._logging._setup_from_dnf_conf(self.conf, file_loggers_only=True)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
+ def _skipped_packages(self, report_problems, transaction):
|
|
|
4f4af9 |
+ """returns set of conflicting packages and set of packages with broken dependency that would
|
|
|
4f4af9 |
+ be additionally installed when --best and --allowerasing"""
|
|
|
4f4af9 |
+ if self._goal.actions & (hawkey.INSTALL | hawkey.UPGRADE | hawkey.UPGRADE_ALL):
|
|
|
4f4af9 |
+ best = True
|
|
|
4f4af9 |
+ else:
|
|
|
4f4af9 |
+ best = False
|
|
|
4f4af9 |
+ ng = deepcopy(self._goal)
|
|
|
4f4af9 |
+ params = {"allow_uninstall": self._allow_erasing,
|
|
|
4f4af9 |
+ "force_best": best,
|
|
|
4f4af9 |
+ "ignore_weak": True}
|
|
|
4f4af9 |
+ ret = ng.run(**params)
|
|
|
4f4af9 |
+ if not ret and report_problems:
|
|
|
4f4af9 |
+ msg = dnf.util._format_resolve_problems(ng.problem_rules())
|
|
|
4f4af9 |
+ logger.warning(msg)
|
|
|
4f4af9 |
+ problem_conflicts = set(ng.problem_conflicts(available=True))
|
|
|
4f4af9 |
+ problem_dependency = set(ng.problem_broken_dependency(available=True)) - problem_conflicts
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ def _nevra(item):
|
|
|
4f4af9 |
+ return hawkey.NEVRA(name=item.name, epoch=item.epoch, version=item.version,
|
|
|
4f4af9 |
+ release=item.release, arch=item.arch)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ # Sometimes, pkg is not in transaction item, therefore, comparing by nevra
|
|
|
4f4af9 |
+ transaction_nevras = [_nevra(tsi) for tsi in transaction]
|
|
|
4f4af9 |
+ skipped_conflicts = set(
|
|
|
4f4af9 |
+ [pkg for pkg in problem_conflicts if _nevra(pkg) not in transaction_nevras])
|
|
|
4f4af9 |
+ skipped_dependency = set(
|
|
|
4f4af9 |
+ [pkg for pkg in problem_dependency if _nevra(pkg) not in transaction_nevras])
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ return skipped_conflicts, skipped_dependency
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def _msg_installed(pkg):
|
|
|
4f4af9 |
name = ucd(pkg)
|
|
|
4f4af9 |
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
|
|
4f4af9 |
index 0bc2c119d0..334000362c 100644
|
|
|
4f4af9 |
--- a/dnf/cli/cli.py
|
|
|
4f4af9 |
+++ b/dnf/cli/cli.py
|
|
|
4f4af9 |
@@ -252,8 +252,12 @@ def do_transaction(self, display=()):
|
|
|
4f4af9 |
trans = None
|
|
|
4f4af9 |
|
|
|
4f4af9 |
if trans:
|
|
|
4f4af9 |
- msg = self.output.post_transaction_output(trans)
|
|
|
4f4af9 |
- logger.info(msg)
|
|
|
4f4af9 |
+ # the post transaction summary is already written to log during
|
|
|
4f4af9 |
+ # Base.do_transaction() so here only print the messages to the
|
|
|
4f4af9 |
+ # user arranged in columns
|
|
|
4f4af9 |
+ print()
|
|
|
4f4af9 |
+ print('\n'.join(self.output.post_transaction_output(trans)))
|
|
|
4f4af9 |
+ print()
|
|
|
4f4af9 |
for tsi in trans:
|
|
|
4f4af9 |
if tsi.state == libdnf.transaction.TransactionItemState_ERROR:
|
|
|
4f4af9 |
raise dnf.exceptions.Error(_('Transaction failed'))
|
|
|
4f4af9 |
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
|
|
|
4f4af9 |
index af8a968770..6d729b63ba 100644
|
|
|
4f4af9 |
--- a/dnf/cli/output.py
|
|
|
4f4af9 |
+++ b/dnf/cli/output.py
|
|
|
4f4af9 |
@@ -21,9 +21,7 @@
|
|
|
4f4af9 |
from __future__ import print_function
|
|
|
4f4af9 |
from __future__ import unicode_literals
|
|
|
4f4af9 |
|
|
|
4f4af9 |
-from copy import deepcopy
|
|
|
4f4af9 |
import fnmatch
|
|
|
4f4af9 |
-import functools
|
|
|
4f4af9 |
import hawkey
|
|
|
4f4af9 |
import itertools
|
|
|
4f4af9 |
import libdnf.transaction
|
|
|
4f4af9 |
@@ -53,51 +51,6 @@
|
|
|
4f4af9 |
logger = logging.getLogger('dnf')
|
|
|
4f4af9 |
|
|
|
4f4af9 |
|
|
|
4f4af9 |
-def _make_lists(transaction):
|
|
|
4f4af9 |
- b = dnf.util.Bunch({
|
|
|
4f4af9 |
- 'downgraded': [],
|
|
|
4f4af9 |
- 'erased': [],
|
|
|
4f4af9 |
- 'erased_clean': [],
|
|
|
4f4af9 |
- 'erased_dep': [],
|
|
|
4f4af9 |
- 'installed': [],
|
|
|
4f4af9 |
- 'installed_group': [],
|
|
|
4f4af9 |
- 'installed_dep': [],
|
|
|
4f4af9 |
- 'installed_weak': [],
|
|
|
4f4af9 |
- 'reinstalled': [],
|
|
|
4f4af9 |
- 'upgraded': [],
|
|
|
4f4af9 |
- 'failed': [],
|
|
|
4f4af9 |
- })
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- for tsi in transaction:
|
|
|
4f4af9 |
- if tsi.state == libdnf.transaction.TransactionItemState_ERROR:
|
|
|
4f4af9 |
- b.failed.append(tsi)
|
|
|
4f4af9 |
- elif tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADE:
|
|
|
4f4af9 |
- b.downgraded.append(tsi)
|
|
|
4f4af9 |
- elif tsi.action == libdnf.transaction.TransactionItemAction_INSTALL:
|
|
|
4f4af9 |
- if tsi.reason == libdnf.transaction.TransactionItemReason_GROUP:
|
|
|
4f4af9 |
- b.installed_group.append(tsi)
|
|
|
4f4af9 |
- elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY:
|
|
|
4f4af9 |
- b.installed_dep.append(tsi)
|
|
|
4f4af9 |
- elif tsi.reason == libdnf.transaction.TransactionItemReason_WEAK_DEPENDENCY:
|
|
|
4f4af9 |
- b.installed_weak.append(tsi)
|
|
|
4f4af9 |
- else:
|
|
|
4f4af9 |
- # TransactionItemReason_USER
|
|
|
4f4af9 |
- b.installed.append(tsi)
|
|
|
4f4af9 |
- elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALL:
|
|
|
4f4af9 |
- b.reinstalled.append(tsi)
|
|
|
4f4af9 |
- elif tsi.action == libdnf.transaction.TransactionItemAction_REMOVE:
|
|
|
4f4af9 |
- if tsi.reason == libdnf.transaction.TransactionItemReason_CLEAN:
|
|
|
4f4af9 |
- b.erased_clean.append(tsi)
|
|
|
4f4af9 |
- elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY:
|
|
|
4f4af9 |
- b.erased_dep.append(tsi)
|
|
|
4f4af9 |
- else:
|
|
|
4f4af9 |
- b.erased.append(tsi)
|
|
|
4f4af9 |
- elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADE:
|
|
|
4f4af9 |
- b.upgraded.append(tsi)
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- return b
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
def _spread_in_columns(cols_count, label, lst):
|
|
|
4f4af9 |
left = itertools.chain((label,), itertools.repeat(''))
|
|
|
4f4af9 |
lst_length = len(lst)
|
|
|
4f4af9 |
@@ -1057,37 +1010,6 @@ def list_group_transaction(self, comps, history, diff):
|
|
|
4f4af9 |
out[0:0] = self._banner(col_data, (_('Group'), _('Packages'), '', ''))
|
|
|
4f4af9 |
return '\n'.join(out)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- def _skipped_packages(self, report_problems, transaction):
|
|
|
4f4af9 |
- """returns set of conflicting packages and set of packages with broken dependency that would
|
|
|
4f4af9 |
- be additionally installed when --best and --allowerasing"""
|
|
|
4f4af9 |
- if self.base._goal.actions & (hawkey.INSTALL | hawkey.UPGRADE | hawkey.UPGRADE_ALL):
|
|
|
4f4af9 |
- best = True
|
|
|
4f4af9 |
- else:
|
|
|
4f4af9 |
- best = False
|
|
|
4f4af9 |
- ng = deepcopy(self.base._goal)
|
|
|
4f4af9 |
- params = {"allow_uninstall": self.base._allow_erasing,
|
|
|
4f4af9 |
- "force_best": best,
|
|
|
4f4af9 |
- "ignore_weak": True}
|
|
|
4f4af9 |
- ret = ng.run(**params)
|
|
|
4f4af9 |
- if not ret and report_problems:
|
|
|
4f4af9 |
- msg = dnf.util._format_resolve_problems(ng.problem_rules())
|
|
|
4f4af9 |
- logger.warning(msg)
|
|
|
4f4af9 |
- problem_conflicts = set(ng.problem_conflicts(available=True))
|
|
|
4f4af9 |
- problem_dependency = set(ng.problem_broken_dependency(available=True)) - problem_conflicts
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- def _nevra(item):
|
|
|
4f4af9 |
- return hawkey.NEVRA(name=item.name, epoch=item.epoch, version=item.version,
|
|
|
4f4af9 |
- release=item.release, arch=item.arch)
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- # Sometimes, pkg is not in transaction item, therefore, comparing by nevra
|
|
|
4f4af9 |
- transaction_nevras = [_nevra(tsi) for tsi in transaction]
|
|
|
4f4af9 |
- skipped_conflicts = set(
|
|
|
4f4af9 |
- [pkg for pkg in problem_conflicts if _nevra(pkg) not in transaction_nevras])
|
|
|
4f4af9 |
- skipped_dependency = set(
|
|
|
4f4af9 |
- [pkg for pkg in problem_dependency if _nevra(pkg) not in transaction_nevras])
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- return skipped_conflicts, skipped_dependency
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
def list_transaction(self, transaction, total_width=None):
|
|
|
4f4af9 |
"""Return a string representation of the transaction in an
|
|
|
4f4af9 |
easy-to-read format.
|
|
|
4f4af9 |
@@ -1102,7 +1024,7 @@ def list_transaction(self, transaction, total_width=None):
|
|
|
4f4af9 |
# in order to display module changes when RPM transaction is empty
|
|
|
4f4af9 |
transaction = []
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- list_bunch = _make_lists(transaction)
|
|
|
4f4af9 |
+ list_bunch = dnf.util._make_lists(transaction)
|
|
|
4f4af9 |
pkglist_lines = []
|
|
|
4f4af9 |
data = {'n' : {}, 'v' : {}, 'r' : {}}
|
|
|
4f4af9 |
a_wid = 0 # Arch can't get "that big" ... so always use the max.
|
|
|
4f4af9 |
@@ -1271,7 +1193,7 @@ def format_line(group):
|
|
|
4f4af9 |
# show skipped conflicting packages
|
|
|
4f4af9 |
if not self.conf.best and self.base._goal.actions & forward_actions:
|
|
|
4f4af9 |
lines = []
|
|
|
4f4af9 |
- skipped_conflicts, skipped_broken = self._skipped_packages(
|
|
|
4f4af9 |
+ skipped_conflicts, skipped_broken = self.base._skipped_packages(
|
|
|
4f4af9 |
report_problems=True, transaction=transaction)
|
|
|
4f4af9 |
skipped_broken = dict((str(pkg), pkg) for pkg in skipped_broken)
|
|
|
4f4af9 |
for pkg in sorted(skipped_conflicts):
|
|
|
4f4af9 |
@@ -1436,13 +1358,8 @@ def format_line(group):
|
|
|
4f4af9 |
max_msg_count, count, msg_pkgs))
|
|
|
4f4af9 |
return ''.join(out)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- def post_transaction_output(self, transaction):
|
|
|
4f4af9 |
- """Returns a human-readable summary of the results of the
|
|
|
4f4af9 |
- transaction.
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- :return: a string containing a human-readable summary of the
|
|
|
4f4af9 |
- results of the transaction
|
|
|
4f4af9 |
- """
|
|
|
4f4af9 |
+ def _pto_callback(self, action, tsis):
|
|
|
4f4af9 |
# Works a bit like calcColumns, but we never overflow a column we just
|
|
|
4f4af9 |
# have a dynamic number of columns.
|
|
|
4f4af9 |
def _fits_in_cols(msgs, num):
|
|
|
4f4af9 |
@@ -1472,61 +1389,33 @@ def _fits_in_cols(msgs, num):
|
|
|
4f4af9 |
col_lens[col] *= -1
|
|
|
4f4af9 |
return col_lens
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- def _tsi_or_pkg_nevra_cmp(item1, item2):
|
|
|
4f4af9 |
- """Compares two transaction items or packages by nevra.
|
|
|
4f4af9 |
- Used as a fallback when tsi does not contain package object.
|
|
|
4f4af9 |
- """
|
|
|
4f4af9 |
- ret = (item1.name > item2.name) - (item1.name < item2.name)
|
|
|
4f4af9 |
- if ret != 0:
|
|
|
4f4af9 |
- return ret
|
|
|
4f4af9 |
- nevra1 = hawkey.NEVRA(name=item1.name, epoch=item1.epoch, version=item1.version,
|
|
|
4f4af9 |
- release=item1.release, arch=item1.arch)
|
|
|
4f4af9 |
- nevra2 = hawkey.NEVRA(name=item2.name, epoch=item2.epoch, version=item2.version,
|
|
|
4f4af9 |
- release=item2.release, arch=item2.arch)
|
|
|
4f4af9 |
- ret = nevra1.evr_cmp(nevra2, self.sack)
|
|
|
4f4af9 |
- if ret != 0:
|
|
|
4f4af9 |
- return ret
|
|
|
4f4af9 |
- return (item1.arch > item2.arch) - (item1.arch < item2.arch)
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- out = ''
|
|
|
4f4af9 |
- list_bunch = _make_lists(transaction)
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- skipped_conflicts, skipped_broken = self._skipped_packages(
|
|
|
4f4af9 |
- report_problems=False, transaction=transaction)
|
|
|
4f4af9 |
- skipped = skipped_conflicts.union(skipped_broken)
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
- for (action, tsis) in [(_('Upgraded'), list_bunch.upgraded),
|
|
|
4f4af9 |
- (_('Downgraded'), list_bunch.downgraded),
|
|
|
4f4af9 |
- (_('Installed'), list_bunch.installed +
|
|
|
4f4af9 |
- list_bunch.installed_group +
|
|
|
4f4af9 |
- list_bunch.installed_weak +
|
|
|
4f4af9 |
- list_bunch.installed_dep),
|
|
|
4f4af9 |
- (_('Reinstalled'), list_bunch.reinstalled),
|
|
|
4f4af9 |
- (_('Skipped'), skipped),
|
|
|
4f4af9 |
- (_('Removed'), list_bunch.erased +
|
|
|
4f4af9 |
- list_bunch.erased_dep +
|
|
|
4f4af9 |
- list_bunch.erased_clean),
|
|
|
4f4af9 |
- (_('Failed'), list_bunch.failed)]:
|
|
|
4f4af9 |
- if not tsis:
|
|
|
4f4af9 |
- continue
|
|
|
4f4af9 |
- msgs = []
|
|
|
4f4af9 |
- out += '\n%s:\n' % action
|
|
|
4f4af9 |
- for tsi in sorted(tsis, key=functools.cmp_to_key(_tsi_or_pkg_nevra_cmp)):
|
|
|
4f4af9 |
- msgs.append(str(tsi))
|
|
|
4f4af9 |
- for num in (8, 7, 6, 5, 4, 3, 2):
|
|
|
4f4af9 |
- cols = _fits_in_cols(msgs, num)
|
|
|
4f4af9 |
- if cols:
|
|
|
4f4af9 |
- break
|
|
|
4f4af9 |
- if not cols:
|
|
|
4f4af9 |
- cols = [-(self.term.columns - 2)]
|
|
|
4f4af9 |
- while msgs:
|
|
|
4f4af9 |
- current_msgs = msgs[:len(cols)]
|
|
|
4f4af9 |
- out += ' '
|
|
|
4f4af9 |
- out += self.fmtColumns(zip(current_msgs, cols), end=u'\n')
|
|
|
4f4af9 |
- msgs = msgs[len(cols):]
|
|
|
4f4af9 |
-
|
|
|
4f4af9 |
+ if not tsis:
|
|
|
4f4af9 |
+ return ''
|
|
|
4f4af9 |
+ out = []
|
|
|
4f4af9 |
+ msgs = []
|
|
|
4f4af9 |
+ out.append('{}:'.format(action))
|
|
|
4f4af9 |
+ for tsi in tsis:
|
|
|
4f4af9 |
+ msgs.append(str(tsi))
|
|
|
4f4af9 |
+ for num in (8, 7, 6, 5, 4, 3, 2):
|
|
|
4f4af9 |
+ cols = _fits_in_cols(msgs, num)
|
|
|
4f4af9 |
+ if cols:
|
|
|
4f4af9 |
+ break
|
|
|
4f4af9 |
+ if not cols:
|
|
|
4f4af9 |
+ cols = [-(self.term.columns - 2)]
|
|
|
4f4af9 |
+ while msgs:
|
|
|
4f4af9 |
+ current_msgs = msgs[:len(cols)]
|
|
|
4f4af9 |
+ out.append(' {}'.format(self.fmtColumns(zip(current_msgs, cols))))
|
|
|
4f4af9 |
+ msgs = msgs[len(cols):]
|
|
|
4f4af9 |
return out
|
|
|
4f4af9 |
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ def post_transaction_output(self, transaction):
|
|
|
4f4af9 |
+ """
|
|
|
4f4af9 |
+ Return a human-readable summary of the transaction. Packages in sections
|
|
|
4f4af9 |
+ are arranged to columns.
|
|
|
4f4af9 |
+ """
|
|
|
4f4af9 |
+ return dnf.util._post_transaction_output(self.base, transaction, self._pto_callback)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
def setup_progress_callbacks(self):
|
|
|
4f4af9 |
"""Set up the progress callbacks and various
|
|
|
4f4af9 |
output bars based on debug level.
|
|
|
4f4af9 |
diff --git a/dnf/util.py b/dnf/util.py
|
|
|
4f4af9 |
index 8cf362706d..0beb04424d 100644
|
|
|
4f4af9 |
--- a/dnf/util.py
|
|
|
4f4af9 |
+++ b/dnf/util.py
|
|
|
4f4af9 |
@@ -24,13 +24,14 @@
|
|
|
4f4af9 |
|
|
|
4f4af9 |
from .pycomp import PY3, basestring
|
|
|
4f4af9 |
from dnf.i18n import _, ucd
|
|
|
4f4af9 |
-from functools import reduce
|
|
|
4f4af9 |
import argparse
|
|
|
4f4af9 |
import dnf
|
|
|
4f4af9 |
import dnf.callback
|
|
|
4f4af9 |
import dnf.const
|
|
|
4f4af9 |
import dnf.pycomp
|
|
|
4f4af9 |
import errno
|
|
|
4f4af9 |
+import functools
|
|
|
4f4af9 |
+import hawkey
|
|
|
4f4af9 |
import itertools
|
|
|
4f4af9 |
import locale
|
|
|
4f4af9 |
import logging
|
|
|
4f4af9 |
@@ -41,6 +42,7 @@
|
|
|
4f4af9 |
import tempfile
|
|
|
4f4af9 |
import time
|
|
|
4f4af9 |
import libdnf.repo
|
|
|
4f4af9 |
+import libdnf.transaction
|
|
|
4f4af9 |
|
|
|
4f4af9 |
logger = logging.getLogger('dnf')
|
|
|
4f4af9 |
|
|
|
4f4af9 |
@@ -195,7 +197,7 @@ def group_by_filter(fn, iterable):
|
|
|
4f4af9 |
def splitter(acc, item):
|
|
|
4f4af9 |
acc[not bool(fn(item))].append(item)
|
|
|
4f4af9 |
return acc
|
|
|
4f4af9 |
- return reduce(splitter, iterable, ([], []))
|
|
|
4f4af9 |
+ return functools.reduce(splitter, iterable, ([], []))
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def insert_if(item, iterable, condition):
|
|
|
4f4af9 |
"""Insert an item into an iterable by a condition."""
|
|
|
4f4af9 |
@@ -504,3 +506,99 @@ def __setattr__(self, what, val):
|
|
|
4f4af9 |
def setter(item):
|
|
|
4f4af9 |
setattr(item, what, val)
|
|
|
4f4af9 |
return list(map(setter, self))
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+def _make_lists(transaction):
|
|
|
4f4af9 |
+ b = Bunch({
|
|
|
4f4af9 |
+ 'downgraded': [],
|
|
|
4f4af9 |
+ 'erased': [],
|
|
|
4f4af9 |
+ 'erased_clean': [],
|
|
|
4f4af9 |
+ 'erased_dep': [],
|
|
|
4f4af9 |
+ 'installed': [],
|
|
|
4f4af9 |
+ 'installed_group': [],
|
|
|
4f4af9 |
+ 'installed_dep': [],
|
|
|
4f4af9 |
+ 'installed_weak': [],
|
|
|
4f4af9 |
+ 'reinstalled': [],
|
|
|
4f4af9 |
+ 'upgraded': [],
|
|
|
4f4af9 |
+ 'failed': [],
|
|
|
4f4af9 |
+ })
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ for tsi in transaction:
|
|
|
4f4af9 |
+ if tsi.state == libdnf.transaction.TransactionItemState_ERROR:
|
|
|
4f4af9 |
+ b.failed.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADE:
|
|
|
4f4af9 |
+ b.downgraded.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.action == libdnf.transaction.TransactionItemAction_INSTALL:
|
|
|
4f4af9 |
+ if tsi.reason == libdnf.transaction.TransactionItemReason_GROUP:
|
|
|
4f4af9 |
+ b.installed_group.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY:
|
|
|
4f4af9 |
+ b.installed_dep.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.reason == libdnf.transaction.TransactionItemReason_WEAK_DEPENDENCY:
|
|
|
4f4af9 |
+ b.installed_weak.append(tsi)
|
|
|
4f4af9 |
+ else:
|
|
|
4f4af9 |
+ # TransactionItemReason_USER
|
|
|
4f4af9 |
+ b.installed.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALL:
|
|
|
4f4af9 |
+ b.reinstalled.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.action == libdnf.transaction.TransactionItemAction_REMOVE:
|
|
|
4f4af9 |
+ if tsi.reason == libdnf.transaction.TransactionItemReason_CLEAN:
|
|
|
4f4af9 |
+ b.erased_clean.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.reason == libdnf.transaction.TransactionItemReason_DEPENDENCY:
|
|
|
4f4af9 |
+ b.erased_dep.append(tsi)
|
|
|
4f4af9 |
+ else:
|
|
|
4f4af9 |
+ b.erased.append(tsi)
|
|
|
4f4af9 |
+ elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADE:
|
|
|
4f4af9 |
+ b.upgraded.append(tsi)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ return b
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+def _post_transaction_output(base, transaction, action_callback):
|
|
|
4f4af9 |
+ """Returns a human-readable summary of the results of the
|
|
|
4f4af9 |
+ transaction.
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ :param action_callback: function generating output for specific action. It
|
|
|
4f4af9 |
+ takes two parameters - action as a string and list of affected packages for
|
|
|
4f4af9 |
+ this action
|
|
|
4f4af9 |
+ :return: a list of lines containing a human-readable summary of the
|
|
|
4f4af9 |
+ results of the transaction
|
|
|
4f4af9 |
+ """
|
|
|
4f4af9 |
+ def _tsi_or_pkg_nevra_cmp(item1, item2):
|
|
|
4f4af9 |
+ """Compares two transaction items or packages by nevra.
|
|
|
4f4af9 |
+ Used as a fallback when tsi does not contain package object.
|
|
|
4f4af9 |
+ """
|
|
|
4f4af9 |
+ ret = (item1.name > item2.name) - (item1.name < item2.name)
|
|
|
4f4af9 |
+ if ret != 0:
|
|
|
4f4af9 |
+ return ret
|
|
|
4f4af9 |
+ nevra1 = hawkey.NEVRA(name=item1.name, epoch=item1.epoch, version=item1.version,
|
|
|
4f4af9 |
+ release=item1.release, arch=item1.arch)
|
|
|
4f4af9 |
+ nevra2 = hawkey.NEVRA(name=item2.name, epoch=item2.epoch, version=item2.version,
|
|
|
4f4af9 |
+ release=item2.release, arch=item2.arch)
|
|
|
4f4af9 |
+ ret = nevra1.evr_cmp(nevra2, base.sack)
|
|
|
4f4af9 |
+ if ret != 0:
|
|
|
4f4af9 |
+ return ret
|
|
|
4f4af9 |
+ return (item1.arch > item2.arch) - (item1.arch < item2.arch)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ list_bunch = dnf.util._make_lists(transaction)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ skipped_conflicts, skipped_broken = base._skipped_packages(
|
|
|
4f4af9 |
+ report_problems=False, transaction=transaction)
|
|
|
4f4af9 |
+ skipped = skipped_conflicts.union(skipped_broken)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ out = []
|
|
|
4f4af9 |
+ for (action, tsis) in [(_('Upgraded'), list_bunch.upgraded),
|
|
|
4f4af9 |
+ (_('Downgraded'), list_bunch.downgraded),
|
|
|
4f4af9 |
+ (_('Installed'), list_bunch.installed +
|
|
|
4f4af9 |
+ list_bunch.installed_group +
|
|
|
4f4af9 |
+ list_bunch.installed_weak +
|
|
|
4f4af9 |
+ list_bunch.installed_dep),
|
|
|
4f4af9 |
+ (_('Reinstalled'), list_bunch.reinstalled),
|
|
|
4f4af9 |
+ (_('Skipped'), skipped),
|
|
|
4f4af9 |
+ (_('Removed'), list_bunch.erased +
|
|
|
4f4af9 |
+ list_bunch.erased_dep +
|
|
|
4f4af9 |
+ list_bunch.erased_clean),
|
|
|
4f4af9 |
+ (_('Failed'), list_bunch.failed)]:
|
|
|
4f4af9 |
+ out.extend(action_callback(
|
|
|
4f4af9 |
+ action, sorted(tsis, key=functools.cmp_to_key(_tsi_or_pkg_nevra_cmp))))
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ return out
|