import dnf-4.2.7-7.el8_1

This commit is contained in:
CentOS Sources 2019-11-05 17:34:18 -05:00 committed by Andrew Lukoshko
commit a7216982e9
13 changed files with 280896 additions and 0 deletions

1
.dnf.metadata Normal file
View File

@ -0,0 +1 @@
5b789329d4fc3e54190e637f1f046232681c8f5f SOURCES/dnf-4.2.7.tar.gz

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/dnf-4.2.7.tar.gz

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,118 @@
From 524950fb6c647194ad9e0d3b7b2195d671424d1c Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 9 Apr 2019 20:54:12 +0200
Subject: [PATCH] Accept multiple specs in repoquery options (RhBug:1667898,1656801)
It allows with repoquery command to use --what* options multiple times
(append option) or add multiple arguments separated by comma.
https://bugzilla.redhat.com/show_bug.cgi?id=1667898
https://bugzilla.redhat.com/show_bug.cgi?id=1656801
---
dnf.spec | 2 +-
dnf/cli/commands/repoquery.py | 39 +++++++++++++++++++++++++--------------
tests/test_repoquery.py | 4 ++--
3 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/dnf.spec b/dnf.spec
index bbbe954..e3002db 100644
--- a/dnf.spec
+++ b/dnf.spec
@@ -1,5 +1,5 @@
# default dependencies
-%global hawkey_version 0.35.1
+%global hawkey_version 0.35.2
%global libcomps_version 0.1.8
%global libmodulemd_version 1.4.0
%global rpm_version 4.14.0
diff --git a/dnf/cli/commands/repoquery.py b/dnf/cli/commands/repoquery.py
index 0e5073f..c31501f 100644
--- a/dnf/cli/commands/repoquery.py
+++ b/dnf/cli/commands/repoquery.py
@@ -126,24 +126,33 @@ class RepoQueryCommand(commands.Command):
help=_('show only results from this ARCH'))
parser.add_argument('-f', '--file', metavar='FILE', nargs='+',
help=_('show only results that owns FILE'))
- parser.add_argument('--whatconflicts', metavar='REQ',
+ parser.add_argument('--whatconflicts', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('show only results that conflict REQ'))
- parser.add_argument('--whatdepends', metavar='REQ',
+ parser.add_argument('--whatdepends', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('shows results that requires, suggests, supplements, enhances,'
'or recommends package provides and files REQ'))
- parser.add_argument('--whatobsoletes', metavar='REQ',
+ parser.add_argument('--whatobsoletes', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('show only results that obsolete REQ'))
- parser.add_argument('--whatprovides', metavar='REQ',
+ parser.add_argument('--whatprovides', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('show only results that provide REQ'))
- parser.add_argument('--whatrequires', metavar='REQ',
+ parser.add_argument('--whatrequires', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('shows results that requires package provides and files REQ'))
- parser.add_argument('--whatrecommends', metavar='REQ',
+ parser.add_argument('--whatrecommends', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('show only results that recommend REQ'))
- parser.add_argument('--whatenhances', metavar='REQ',
+ parser.add_argument('--whatenhances', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('show only results that enhance REQ'))
- parser.add_argument('--whatsuggests', metavar='REQ',
+ parser.add_argument('--whatsuggests', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('show only results that suggest REQ'))
- parser.add_argument('--whatsupplements', metavar='REQ',
+ parser.add_argument('--whatsupplements', default=[], action=OptionParser._SplitCallback,
+ metavar='REQ',
help=_('show only results that supplement REQ'))
whatrequiresform = parser.add_mutually_exclusive_group()
whatrequiresform.add_argument("--alldeps", action="store_true",
@@ -354,10 +363,12 @@ class RepoQueryCommand(commands.Command):
return t.union(done)
def by_all_deps(self, requires_name, depends_name, query):
- name = requires_name or depends_name
- defaultquery = query.intersection(dnf.subject.Subject(name).get_best_query(
- self.base.sack, with_provides=False, with_filenames=False))
- requiresquery = query.filter(requires__glob=name)
+ names = requires_name or depends_name
+ defaultquery = self.base.sack.query().filter(empty=True)
+ for name in names:
+ defaultquery.union(query.intersection(dnf.subject.Subject(name).get_best_query(
+ self.base.sack, with_provides=False, with_filenames=False)))
+ requiresquery = query.filter(requires__glob=names)
if depends_name:
requiresquery = requiresquery.union(query.filter(recommends__glob=depends_name))
requiresquery = requiresquery.union(query.filter(enhances__glob=depends_name))
@@ -446,7 +457,7 @@ class RepoQueryCommand(commands.Command):
if self.opts.whatobsoletes:
q.filterm(obsoletes=self.opts.whatobsoletes)
if self.opts.whatprovides:
- query_for_provide = q.filter(provides__glob=[self.opts.whatprovides])
+ query_for_provide = q.filter(provides__glob=self.opts.whatprovides)
if query_for_provide:
q = query_for_provide
else:
diff --git a/tests/test_repoquery.py b/tests/test_repoquery.py
index 9e6cc7d..9182537 100644
--- a/tests/test_repoquery.py
+++ b/tests/test_repoquery.py
@@ -78,8 +78,8 @@ class ArgParseTest(tests.support.TestCase):
def test_parse(self):
tests.support.command_configure(self.cmd, ['--whatrequires', 'prudence'])
- self.assertIsNone(self.cmd.opts.whatprovides)
- self.assertEqual(self.cmd.opts.whatrequires, 'prudence')
+ self.assertEqual(self.cmd.opts.whatprovides, [])
+ self.assertEqual(self.cmd.opts.whatrequires, ['prudence'])
self.assertEqual(self.cmd.opts.queryformat,
dnf.cli.commands.repoquery.QFORMAT_DEFAULT)
--
libgit2 0.28.2

View File

@ -0,0 +1,99 @@
From d53492bea1ed9c08710af75c54abea9a69f82757 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Wed, 19 Jun 2019 12:42:31 +0200
Subject: [PATCH] Prevent switching modules in all cases (RhBug:1706215)
The test moved into cli/do_transaction() allows to apply the restriction
for all commands.
https://bugzilla.redhat.com/show_bug.cgi?id=1706215
---
dnf/cli/cli.py | 16 ++++++++++++++++
dnf/cli/commands/module.py | 23 -----------------------
2 files changed, 16 insertions(+), 23 deletions(-)
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
index 09642d1..6ac18fa 100644
--- a/dnf/cli/cli.py
+++ b/dnf/cli/cli.py
@@ -142,6 +142,13 @@ def print_versions(pkgs, base, output):
# sm_ui_date(pkg.committime)))
+def report_module_switch(switchedModules):
+ msg1 = _("The operation would result in switching of module '{0}' stream '{1}' to "
+ "stream '{2}'")
+ for moduleName, streams in switchedModules.items():
+ logger.warning(msg1.format(moduleName, streams[0], streams[1]))
+
+
class BaseCli(dnf.Base):
"""This is the base class for yum cli."""
@@ -157,6 +164,15 @@ class BaseCli(dnf.Base):
:param display: `rpm.callback.TransactionProgress` object(s)
:return: history database transaction ID or None
"""
+ if dnf.base.WITH_MODULES:
+ switchedModules = dict(self._moduleContainer.getSwitchedStreams())
+ if switchedModules:
+ report_module_switch(switchedModules)
+ msg = _("It is not possible to switch enabled streams of a module.\n"
+ "It is recommended to remove all installed content from the module, and "
+ "reset the module using 'dnf module reset <module_name>' command. After "
+ "you reset the module, you can install the other stream.")
+ raise dnf.exceptions.Error(msg)
trans = self.transaction
pkg_str = self.output.list_transaction(trans)
diff --git a/dnf/cli/commands/module.py b/dnf/cli/commands/module.py
index 143bfaa..acaa42c 100644
--- a/dnf/cli/commands/module.py
+++ b/dnf/cli/commands/module.py
@@ -32,13 +32,6 @@ import dnf.module.module_base
import dnf.exceptions
-def report_module_switch(switchedModules):
- msg1 = _("The operation would result in switching of module '{0}' stream '{1}' to "
- "stream '{2}'")
- for moduleName, streams in switchedModules.items():
- logger.warning(msg1.format(moduleName, streams[0], streams[1]))
-
-
class ModuleCommand(commands.Command):
class SubCommand(commands.Command):
@@ -122,14 +115,6 @@ class ModuleCommand(commands.Command):
libdnf.module.ModulePackageContainer.ModuleErrorType_ERROR_IN_DEFAULTS:
raise e
logger.error(str(e))
- switchedModules = dict(self.base._moduleContainer.getSwitchedStreams())
- if switchedModules:
- report_module_switch(switchedModules)
- msg = _("It is not possible to switch enabled streams of a module.\n"
- "It is recommended to remove all installed content from the module, and "
- "reset the module using 'dnf module reset <module_name>' command. After "
- "you reset the module, you can enable the other stream.")
- raise dnf.exceptions.Error(msg)
class DisableSubCommand(SubCommand):
@@ -193,14 +178,6 @@ class ModuleCommand(commands.Command):
if e.no_match_group_specs or e.error_group_specs:
raise e
logger.error(str(e))
- switchedModules = dict(self.base._moduleContainer.getSwitchedStreams())
- if switchedModules:
- report_module_switch(switchedModules)
- msg = _("It is not possible to switch enabled streams of a module.\n"
- "It is recommended to remove all installed content from the module, and "
- "reset the module using 'dnf module reset <module_name>' command. After "
- "you reset the module, you can install the other stream.")
- raise dnf.exceptions.Error(msg)
class UpdateSubCommand(SubCommand):
--
libgit2 0.28.2

View File

@ -0,0 +1,435 @@
From f6ffdce83004acdb2325d966ad348dfe63fb55f8 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Mon, 3 Jun 2019 19:26:55 +0200
Subject: [PATCH 1/5] [transaction] Set an error for first tsi in unknown state
(RhBug:1737328)
It should prevent "TransactionItem state is not set" in case of multiple
same NEVRASs and single with an error.
https://bugzilla.redhat.com/show_bug.cgi?id=1737328
---
dnf/yum/rpmtrans.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dnf/yum/rpmtrans.py b/dnf/yum/rpmtrans.py
index 6a60b5a08..50d8b81cb 100644
--- a/dnf/yum/rpmtrans.py
+++ b/dnf/yum/rpmtrans.py
@@ -386,6 +386,10 @@ class RPMTransaction(object):
msg = "Error unpacking rpm package %s" % tsi.pkg
for display in self.displays:
display.error(msg)
+ for tsi1 in transaction_list:
+ if tsi1.state == libdnf.transaction.TransactionItemState_UNKNOWN:
+ tsi1.state = libdnf.transaction.TransactionItemState_ERROR
+ return
tsi.state = libdnf.transaction.TransactionItemState_ERROR
def _scriptError(self, amount, total, key):
--
2.21.0
From c07beb11b8f085a4ced74502c70d48b4db4e4099 Mon Sep 17 00:00:00 2001
From: Daniel Mach <dmach@redhat.com>
Date: Wed, 5 Jun 2019 08:29:03 +0200
Subject: [PATCH 2/5] [history] Don't store failed transactions as succeeded.
(RhBug:1737328)
---
dnf/base.py | 7 ++++---
dnf/db/history.py | 16 ++++++++++------
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/dnf/base.py b/dnf/base.py
index 7a388ecf4..add64036b 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -987,7 +987,7 @@ class Base(object):
# particular element failed and if not, decide that is the
# case.
failed = [el for el in self._ts if el.Failed()]
- if len(failed) > 0:
+ if failed:
for te in failed:
te_nevra = dnf.util._te_nevra(te)
for tsi in self._transaction:
@@ -996,6 +996,7 @@ class Base(object):
errstring = _('Errors occurred during transaction.')
logger.debug(errstring)
+ self.history.end(rpmdbv)
else:
login = dnf.util.get_effective_login()
msg = _("Failed to obtain the transaction lock "
@@ -1006,7 +1007,7 @@ class Base(object):
else:
if self._record_history():
herrors = [ucd(x) for x in errors]
- self.history.end(rpmdbv, 2, errors=herrors)
+ self.history.end(rpmdbv)
logger.critical(_("Transaction couldn't start:"))
for e in errors:
@@ -1069,7 +1070,7 @@ class Base(object):
count = display_banner(tsi.pkg, count)
rpmdbv = rpmdb_sack._rpmdb_version()
- self.history.end(rpmdbv, 0)
+ self.history.end(rpmdbv)
timer()
self._trans_success = True
diff --git a/dnf/db/history.py b/dnf/db/history.py
index dc9c53b70..7f22f97c1 100644
--- a/dnf/db/history.py
+++ b/dnf/db/history.py
@@ -486,14 +486,18 @@ class SwdbInterface(object):
self.swdb.log_error(self._tid, error)
'''
- # TODO: rename to end_transaction?
- def end(self, end_rpmdb_version="", return_code=0, errors=None):
- assert return_code or not errors
- # TODO: fix return_code
- return_code = not bool(return_code)
+ def end(self, end_rpmdb_version="", return_code=None, errors=None):
if not hasattr(self, '_tid'):
return # Failed at beg() time
+ if return_code is None:
+ # return_code/state auto-detection
+ return_code = libdnf.transaction.TransactionState_DONE
+ for tsi in self.rpm:
+ if tsi.state == libdnf.transaction.TransactionItemState_ERROR:
+ return_code = libdnf.transaction.TransactionState_ERROR
+ break
+
for file_descriptor, line in self._output:
self.swdb.addConsoleOutputLine(file_descriptor, line)
self._output = []
@@ -501,7 +505,7 @@ class SwdbInterface(object):
self.swdb.endTransaction(
int(time.time()),
str(end_rpmdb_version),
- bool(return_code)
+ return_code,
)
# Closing and cleanup is done in the close() method.
--
2.21.0
From 5302f0fbf977e6447b5a00adabb34b1c01fe7e55 Mon Sep 17 00:00:00 2001
From: Daniel Mach <dmach@redhat.com>
Date: Wed, 5 Jun 2019 21:10:05 +0200
Subject: [PATCH 3/5] [transaction] Add RPMCALLBACK_INST_{START,STOP} callback
handlers. (RhBug:1737328)
---
dnf/yum/rpmtrans.py | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/dnf/yum/rpmtrans.py b/dnf/yum/rpmtrans.py
index 50d8b81cb..0834a8c82 100644
--- a/dnf/yum/rpmtrans.py
+++ b/dnf/yum/rpmtrans.py
@@ -262,6 +262,10 @@ class RPMTransaction(object):
return self._instOpenFile(key)
elif what == rpm.RPMCALLBACK_INST_CLOSE_FILE:
self._instCloseFile(key)
+ elif what == rpm.RPMCALLBACK_INST_START:
+ self._inst_start(key)
+ elif what == rpm.RPMCALLBACK_INST_STOP:
+ self._inst_stop(key)
elif what == rpm.RPMCALLBACK_INST_PROGRESS:
self._instProgress(amount, total, key)
elif what == rpm.RPMCALLBACK_UNINST_START:
@@ -321,12 +325,17 @@ class RPMTransaction(object):
return self.fd.fileno()
def _instCloseFile(self, key):
- transaction_list = self._extract_cbkey(key)
self.fd.close()
self.fd = None
+ def _inst_start(self, key):
+ pass
+
+ def _inst_stop(self, key):
if self.test or not self.trans_running:
return
+
+ transaction_list = self._extract_cbkey(key)
for tsi in transaction_list:
if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
tsi.state = libdnf.transaction.TransactionItemState_DONE
@@ -376,6 +385,10 @@ class RPMTransaction(object):
def _cpioError(self, key):
transaction_list = self._extract_cbkey(key)
+ for tsi in transaction_list:
+ if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
+ tsi.state = libdnf.transaction.TransactionItemState_ERROR
+ break
msg = "Error in cpio payload of rpm package %s" % transaction_list[0].pkg
for display in self.displays:
display.error(msg)
@@ -386,11 +399,11 @@ class RPMTransaction(object):
msg = "Error unpacking rpm package %s" % tsi.pkg
for display in self.displays:
display.error(msg)
- for tsi1 in transaction_list:
- if tsi1.state == libdnf.transaction.TransactionItemState_UNKNOWN:
- tsi1.state = libdnf.transaction.TransactionItemState_ERROR
+
+ for tsi in transaction_list:
+ if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
+ tsi.state = libdnf.transaction.TransactionItemState_ERROR
return
- tsi.state = libdnf.transaction.TransactionItemState_ERROR
def _scriptError(self, amount, total, key):
# "amount" carries the failed scriptlet tag,
--
2.21.0
From a3cc8343ff418cca386a0a11f331ebe08e70bae6 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Thu, 13 Jun 2019 12:02:07 +0200
Subject: [PATCH 4/5] Change synchronization of rpm transaction to swdb
(RhBug:1737328)
Originally the state of transaction element was changed by callbacks,
but this approach cannot ensure that all elements will be marked
correctly in case of error when rpm could skip some of elements.
The new approach only synchronize the states of all elements in
transaction after transaction is finished.
https://bugzilla.redhat.com/show_bug.cgi?id=1737328
---
dnf/base.py | 21 +++++----------------
dnf/util.py | 36 ++++++++++++++++++++++++++++++++++++
dnf/yum/rpmtrans.py | 22 +++-------------------
3 files changed, 44 insertions(+), 35 deletions(-)
diff --git a/dnf/base.py b/dnf/base.py
index add64036b..237ad397d 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -978,6 +978,7 @@ class Base(object):
os.nice(onice)
except:
pass
+ dnf.util._sync_rpm_trans_with_swdb(self._ts, self._transaction)
if errors is None:
pass
@@ -987,17 +988,7 @@ class Base(object):
# particular element failed and if not, decide that is the
# case.
failed = [el for el in self._ts if el.Failed()]
- if failed:
- for te in failed:
- te_nevra = dnf.util._te_nevra(te)
- for tsi in self._transaction:
- if str(tsi) == te_nevra:
- tsi.state = libdnf.transaction.TransactionItemState_ERROR
-
- errstring = _('Errors occurred during transaction.')
- logger.debug(errstring)
- self.history.end(rpmdbv)
- else:
+ if not failed:
login = dnf.util.get_effective_login()
msg = _("Failed to obtain the transaction lock "
"(logged in as: %s).")
@@ -1005,13 +996,11 @@ class Base(object):
msg = _('Could not run transaction.')
raise dnf.exceptions.Error(msg)
else:
- if self._record_history():
- herrors = [ucd(x) for x in errors]
- self.history.end(rpmdbv)
-
logger.critical(_("Transaction couldn't start:"))
for e in errors:
- logger.critical(e[0]) # should this be 'to_unicoded'?
+ logger.critical(ucd(e[0]))
+ if self._record_history() and not self._ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST):
+ self.history.end(rpmdbv)
msg = _("Could not run transaction.")
raise dnf.exceptions.Error(msg)
diff --git a/dnf/util.py b/dnf/util.py
index 2f1abe626..9d0288e5a 100644
--- a/dnf/util.py
+++ b/dnf/util.py
@@ -396,6 +396,42 @@ def _te_nevra(te):
return nevra + te.V() + '-' + te.R() + '.' + te.A()
+def _sync_rpm_trans_with_swdb(rpm_transaction, swdb_transaction):
+ revert_actions = {libdnf.transaction.TransactionItemAction_DOWNGRADED,
+ libdnf.transaction.TransactionItemAction_OBSOLETED,
+ libdnf.transaction.TransactionItemAction_REMOVE,
+ libdnf.transaction.TransactionItemAction_UPGRADED,
+ libdnf.transaction.TransactionItemAction_REINSTALLED}
+ cached_tsi = [tsi for tsi in swdb_transaction]
+ el_not_found = False
+ error = False
+ for rpm_el in rpm_transaction:
+ te_nevra = _te_nevra(rpm_el)
+ tsi = rpm_el.Key()
+ if tsi is None or not hasattr(tsi, "pkg"):
+ for tsi_candidate in cached_tsi:
+ if tsi_candidate.state != libdnf.transaction.TransactionItemState_UNKNOWN:
+ continue
+ if tsi_candidate.action not in revert_actions:
+ continue
+ if str(tsi_candidate) == te_nevra:
+ tsi = tsi_candidate
+ break
+ if tsi is None or not hasattr(tsi, "pkg"):
+ logger.critical(_("TransactionItem not found for key: {}").format(te_nevra))
+ el_not_found = True
+ continue
+ if rpm_el.Failed():
+ tsi.state = libdnf.transaction.TransactionItemState_ERROR
+ error = True
+ else:
+ tsi.state = libdnf.transaction.TransactionItemState_DONE
+ if error:
+ logger.debug(_('Errors occurred during transaction.'))
+
+ return el_not_found
+
+
class tmpdir(object):
def __init__(self):
prefix = '%s-' % dnf.const.PREFIX
diff --git a/dnf/yum/rpmtrans.py b/dnf/yum/rpmtrans.py
index 0834a8c82..8a5bd4731 100644
--- a/dnf/yum/rpmtrans.py
+++ b/dnf/yum/rpmtrans.py
@@ -336,10 +336,7 @@ class RPMTransaction(object):
return
transaction_list = self._extract_cbkey(key)
- for tsi in transaction_list:
- if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
- tsi.state = libdnf.transaction.TransactionItemState_DONE
- break
+ tsi = transaction_list[0]
for display in self.displays:
display.filelog(tsi.pkg, tsi.action)
@@ -370,10 +367,7 @@ class RPMTransaction(object):
def _unInstStop(self, key):
transaction_list = self._extract_cbkey(key)
- for tsi in transaction_list:
- if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
- tsi.state = libdnf.transaction.TransactionItemState_DONE
- break
+ tsi = transaction_list[0]
for display in self.displays:
display.filelog(tsi.pkg, tsi.action)
@@ -385,26 +379,16 @@ class RPMTransaction(object):
def _cpioError(self, key):
transaction_list = self._extract_cbkey(key)
- for tsi in transaction_list:
- if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
- tsi.state = libdnf.transaction.TransactionItemState_ERROR
- break
msg = "Error in cpio payload of rpm package %s" % transaction_list[0].pkg
for display in self.displays:
display.error(msg)
def _unpackError(self, key):
transaction_list = self._extract_cbkey(key)
- tsi = transaction_list[0]
- msg = "Error unpacking rpm package %s" % tsi.pkg
+ msg = "Error unpacking rpm package %s" % transaction_list[0].pkg
for display in self.displays:
display.error(msg)
- for tsi in transaction_list:
- if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
- tsi.state = libdnf.transaction.TransactionItemState_ERROR
- return
-
def _scriptError(self, amount, total, key):
# "amount" carries the failed scriptlet tag,
# "total" carries fatal/non-fatal status
--
2.21.0
From 91aa07fe7b7f01727f2eb5d231fdeb16bd82a872 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 25 Jun 2019 11:44:37 +0200
Subject: [PATCH 5/5] Add detailed debug login for swdb/rpm transaction
(RhBug:1737328)
The logging is required to investigate the issue with tsi.state unknown.
The logging will be triggered only when transaction element
synchronization failed.
---
dnf/util.py | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/dnf/util.py b/dnf/util.py
index 9d0288e5a..71f61ab52 100644
--- a/dnf/util.py
+++ b/dnf/util.py
@@ -396,6 +396,23 @@ def _te_nevra(te):
return nevra + te.V() + '-' + te.R() + '.' + te.A()
+def _log_rpm_trans_with_swdb(rpm_transaction, swdb_transaction):
+ logger.debug("Logging transaction elements")
+ for rpm_el in rpm_transaction:
+ tsi = rpm_el.Key()
+ tsi_state = None
+ if tsi is not None:
+ tsi_state = tsi.state
+ msg = "RPM element: '{}', Key(): '{}', Key state: '{}', Failed() '{}': ".format(
+ _te_nevra(rpm_el), tsi, tsi_state, rpm_el.Failed())
+ logger.debug(msg)
+ for tsi in swdb_transaction:
+ msg = "SWDB element: '{}', State: '{}', Action: '{}', From repo: '{}', Reason: '{}', " \
+ "Get reason: '{}'".format(str(tsi), tsi.state, tsi.action, tsi.from_repo, tsi.reason,
+ tsi.get_reason())
+ logger.debug(msg)
+
+
def _sync_rpm_trans_with_swdb(rpm_transaction, swdb_transaction):
revert_actions = {libdnf.transaction.TransactionItemAction_DOWNGRADED,
libdnf.transaction.TransactionItemAction_OBSOLETED,
@@ -426,10 +443,14 @@ def _sync_rpm_trans_with_swdb(rpm_transaction, swdb_transaction):
error = True
else:
tsi.state = libdnf.transaction.TransactionItemState_DONE
+ for tsi in cached_tsi:
+ if tsi.state == libdnf.transaction.TransactionItemState_UNKNOWN:
+ logger.critical(_("TransactionSWDBItem not found for key: {}").format(str(tsi)))
+ el_not_found = True
if error:
logger.debug(_('Errors occurred during transaction.'))
-
- return el_not_found
+ if el_not_found:
+ _log_rpm_trans_with_swdb(rpm_transaction, cached_tsi)
class tmpdir(object):
--
2.21.0

View File

@ -0,0 +1,82 @@
From 6a6ab3e12b4fe0f3fc402a6b99932640fabccc32 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Wed, 3 Jul 2019 10:49:20 +0200
Subject: [PATCH 1/2] Method to get catched rpm errors from RPMTransaction
(RhBug:1677199)
This method enables iterating through messages logged by underlaying
rpm. The messages could be then logged by dnf, printed to user...
---
dnf/yum/rpmtrans.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/dnf/yum/rpmtrans.py b/dnf/yum/rpmtrans.py
index 8a5bd4731..b0fd9b6eb 100644
--- a/dnf/yum/rpmtrans.py
+++ b/dnf/yum/rpmtrans.py
@@ -210,6 +210,12 @@ class RPMTransaction(object):
except IOError:
pass
+ def messages(self):
+ messages = self._scriptOutput()
+ if messages:
+ for line in messages.splitlines():
+ yield ucd(line)
+
def _scriptout(self):
msgs = self._scriptOutput()
for display in self.displays:
--
2.21.0
From 61e0b7c553fe0c04dfeb3b6d4c16fa36e4eb26f4 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Wed, 3 Jul 2019 10:54:42 +0200
Subject: [PATCH 2/2] Print rpm error messages during transaction
(RhBug:1677199)
This patch lets the rpm error messages to be passed on to the user.
Original code basically considered all rpm errors as "Failed to obtain
the transaction lock", which is obviously not always the case. Now dnf
prints out original rpm messages so that user could find out what the
real problem is.
https://bugzilla.redhat.com/show_bug.cgi?id=1677199
---
dnf/base.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/dnf/base.py b/dnf/base.py
index 237ad397d..2c5d17e8b 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -983,16 +983,16 @@ class Base(object):
if errors is None:
pass
elif len(errors) == 0:
- # this is a particularly tricky case happening also when rpm failed
- # to obtain the transaction lock. We can only try to see if a
- # particular element failed and if not, decide that is the
- # case.
+ # If there is no failing element it means that some "global" error
+ # occured (like rpm failed to obtain the transaction lock). Just pass
+ # the rpm logs on to the user and raise an Error.
+ # If there are failing elements the problem is related to those
+ # elements and the Error is raised later, after saving the failure
+ # to the history and printing out the transaction table to user.
failed = [el for el in self._ts if el.Failed()]
if not failed:
- login = dnf.util.get_effective_login()
- msg = _("Failed to obtain the transaction lock "
- "(logged in as: %s).")
- logger.critical(msg, login)
+ for msg in cb.messages():
+ logger.critical(_('RPM: {}').format(msg))
msg = _('Could not run transaction.')
raise dnf.exceptions.Error(msg)
else:
--
2.21.0

View File

@ -0,0 +1,93 @@
From 4662a3d342de4be584812267c5b59ed9c1f9c44e Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 25 Jun 2019 18:54:54 +0200
Subject: [PATCH] Report missing default profile as an error (RhBug:1669527,1724564)
The behavior where module install command doesn't install any package
when there are no default profiles was recognized by users as an
unexpected behavior.
The patch allows DNF to fail when no default profile is available.
https://bugzilla.redhat.com/show_bug.cgi?id=1669527
https://bugzilla.redhat.com/show_bug.cgi?id=1724564
---
dnf/module/module_base.py | 27 +++++++++++++++++++++++----
tests/test_modules.py | 12 ++----------
2 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/dnf/module/module_base.py b/dnf/module/module_base.py
index 83e5e4a..ea56ad0 100644
--- a/dnf/module/module_base.py
+++ b/dnf/module/module_base.py
@@ -83,21 +83,40 @@ class ModuleBase(object):
if nsvcap.profile:
profiles.extend(latest_module.getProfiles(nsvcap.profile))
if not profiles:
- logger.error(_("Unable to match profile in argument {}").format(spec))
+ available_profiles = latest_module.getProfiles()
+ if available_profiles:
+ profile_names = ", ".join(
+ [profile.getName() for profile in available_profiles])
+ msg = _("Unable to match profile for argument {}. Available "
+ "profiles for '{}:{}': {}").format(
+ spec, name, stream, profile_names)
+ else:
+ msg = _("Unable to match profile for argument {}").format(spec)
+ logger.error(msg)
no_match_specs.append(spec)
continue
else:
profiles_strings = self.base._moduleContainer.getDefaultProfiles(
name, stream)
if not profiles_strings:
- logger.error(_("No default profiles for module {}:{}").format(
- name, stream))
+ available_profiles = latest_module.getProfiles()
+ if available_profiles:
+ profile_names = ", ".join(
+ [profile.getName() for profile in available_profiles])
+ msg = _("No default profiles for module {}:{}. Available profiles"
+ ": {}").format(
+ name, stream, profile_names)
+ else:
+ msg = _("No default profiles for module {}:{}").format(name, stream)
+ logger.error(msg)
+ no_match_specs.append(spec)
for profile in set(profiles_strings):
module_profiles = latest_module.getProfiles(profile)
if not module_profiles:
logger.error(
- _("Profile {} not matched for module {}:{}").format(
+ _("Default profile {} not available in module {}:{}").format(
profile, name, stream))
+ no_match_specs.append(spec)
profiles.extend(module_profiles)
for profile in profiles:
diff --git a/tests/test_modules.py b/tests/test_modules.py
index d5fde4f..49e7718 100644
--- a/tests/test_modules.py
+++ b/tests/test_modules.py
@@ -274,16 +274,8 @@ class ModuleTest(unittest.TestCase):
def test_install_implicit_empty_default_profile(self):
# install module without a 'default' profile
- # -> no packages should be installed, just module enablement
- self.module_base.install(["m4:1.4.18"])
-
- self.assertEqual(self.base._moduleContainer.getModuleState("m4"),
- libdnf.module.ModulePackageContainer.ModuleState_ENABLED)
- self.assertEqual(self.base._moduleContainer.getEnabledStream("m4"), "1.4.18")
- self.assertEqual(list(self.base._moduleContainer.getInstalledProfiles("m4")), [])
-
- self.base.resolve()
- self.assertInstalls([])
+ # -> It should raise an error
+ self.assertRaises(dnf.exceptions.MarkingErrors, self.module_base.install, ["m4:1.4.18"])
# dnf module upgrade / dnf upgrade @
--
libgit2 0.28.2

View File

@ -0,0 +1,33 @@
From c638887211b3d9c0b3b1fcb6eb6b62f384d2c263 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Mon, 22 Jul 2019 09:29:42 +0200
Subject: [PATCH] [doc] Describe a behavior when plugin is removed (RhBug:1700741)
When plugin is removed or obsoleted all hooks of removed plugins after
transaction are skipped. The behavior was added because some
of dependencies of the plugin could be also removed and unavailable in
memory. We apply the same behavior also for obsoleted plugins, because
we suggest that obsoleting plugin could have a different code base.
The behavior is not applicable for downgrades or upgrades.
https://bugzilla.redhat.com/show_bug.cgi?id=1700741
---
doc/api_plugins.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/api_plugins.rst b/doc/api_plugins.rst
index f5d9829..5015e42 100644
--- a/doc/api_plugins.rst
+++ b/doc/api_plugins.rst
@@ -62,6 +62,7 @@ When DNF CLI runs it loads the plugins found in the paths during the CLI's initi
.. method:: transaction
Plugin can override this. This hook is called immediately after a successful transaction.
+ Plugins that were removed or obsoleted by the transaction will not run the transaction hook.
You may want to see the comparison with `yum plugin hook API`_.
--
libgit2 0.28.2

View File

@ -0,0 +1,45 @@
From 60a8f5e3f0500720077b200ce3be46772db4f093 Mon Sep 17 00:00:00 2001
From: Aleš Matěj <amatej@redhat.com>
Date: Mon, 24 Jun 2019 16:13:28 +0200
Subject: [PATCH] Prevent printing empty Error Summary (RhBug: 1690414)
When test transaction fails we generate Error Summary but it contains
information only if the error happened because of lacking disk space
otherwise we get the headline "Error Summary" without any text this
commit prevents this.
---
dnf/base.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/dnf/base.py b/dnf/base.py
index 2c5d17e..0f8b77e 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -858,8 +858,12 @@ class Base(object):
for descr in tserrors:
errstring += ' %s\n' % ucd(descr)
- raise dnf.exceptions.Error(errstring + '\n' +
- self._trans_error_summary(errstring))
+ summary = self._trans_error_summary(errstring)
+ if summary:
+ errstring += '\n' + summary
+
+ raise dnf.exceptions.Error(errstring)
+
logger.info(_('Transaction test succeeded.'))
timer()
@@ -911,6 +915,9 @@ class Base(object):
'At least %dMB more space needed on the %s filesystem.',
disk[k]) % (disk[k], k) + '\n'
+ if not summary:
+ return None
+
summary = _('Error Summary') + '\n-------------\n' + summary
return summary
--
libgit2 0.28.2

View File

@ -0,0 +1,33 @@
From 5b83b191574d43299bb6d3212df06c6f20c818e7 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Wed, 28 Aug 2019 09:52:40 +0200
Subject: [PATCH] Fix: --setopt and repo with dots
The "--setopt" have had a problem with repositories with dots in id.
Repository id may contain dots but option name can't. ->
So, the last dot is delimiter and not the first one.
Example:
"--setopt=re.po.option=value " was parsed as repo id "re" and option
"po.option". Correct result would be repo id "re.po" and option
"option".
---
dnf/cli/option_parser.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dnf/cli/option_parser.py b/dnf/cli/option_parser.py
index 4b6599c..76fcb95 100644
--- a/dnf/cli/option_parser.py
+++ b/dnf/cli/option_parser.py
@@ -99,7 +99,7 @@ class OptionParser(argparse.ArgumentParser):
logger.warning(_("Setopt argument has no value: %s"), values)
return
k, v = vals
- period = k.find('.')
+ period = k.rfind('.')
if period != -1:
repo = k[:period]
k = k[period+1:]
--
libgit2 0.28.2

View File

@ -0,0 +1,49 @@
From a5c4a994f8ad2764ca8f971c39f189d5f9d7d337 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 3 Sep 2019 11:01:51 +0200
Subject: [PATCH] Keep installed packages in upgrade job (RhBug:1728252,1644241,1741381)
In combination with marking of job as TARGETED it prevents from
reinstalling of modified packages with same NEVRA.
https://bugzilla.redhat.com/show_bug.cgi?id=1728252
https://bugzilla.redhat.com/show_bug.cgi?id=1644241
https://bugzilla.redhat.com/show_bug.cgi?id=1741381
Closes: #1474
Approved by: m-blaha
---
dnf/base.py | 3 ---
dnf/module/module_base.py | 2 +-
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/dnf/base.py b/dnf/base.py
index b2ced61..628c154 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -1968,9 +1968,6 @@ class Base(object):
obsoletes=q.installed().union(q.upgrades()))
# add obsoletes into transaction
q = q.union(obsoletes)
- # provide only available packages to solver otherwise selection of available
- # possibilities will be ignored
- q = q.available()
if reponame is not None:
q.filterm(reponame=reponame)
q = self._merge_update_filters(q, pkg_spec=pkg_spec)
diff --git a/dnf/module/module_base.py b/dnf/module/module_base.py
index 976d730..ce70f63 100644
--- a/dnf/module/module_base.py
+++ b/dnf/module/module_base.py
@@ -214,7 +214,7 @@ class ModuleBase(object):
if not upgrade_package_set:
logger.error(_("Unable to match profile in argument {}").format(spec))
- query = self.base.sack.query().available().filterm(name=upgrade_package_set)
+ query = self.base.sack.query().filterm(name=upgrade_package_set)
if query:
sltr = dnf.selector.Selector(self.base.sack)
sltr.set(pkg=query)
--
libgit2 0.28.2

2483
SPECS/dnf.spec Normal file

File diff suppressed because it is too large Load Diff