import dnf-4.2.17-6.el8

This commit is contained in:
CentOS Sources 2020-04-28 05:42:21 -04:00 committed by Andrew Lukoshko
parent a7216982e9
commit 4c31b89508
29 changed files with 264964 additions and 250979 deletions

View File

@ -1 +1 @@
5b789329d4fc3e54190e637f1f046232681c8f5f SOURCES/dnf-4.2.7.tar.gz
535f46b9a5242a315e1269a59372362013a5a6f0 SOURCES/dnf-4.2.17.tar.gz

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/dnf-4.2.7.tar.gz
SOURCES/dnf-4.2.17.tar.gz

View File

@ -0,0 +1,101 @@
From 8bcd196fd95e70fd1f0be16d2c274e39a1cabe2e Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Thu, 21 Nov 2019 11:45:03 +0100
Subject: [PATCH] Do a substitution of variables in repo_id (RhBug:1748841)
Example of repo file:
[test-$basearch-$releasever]
Name=Test-$basearch-$releasever
baseurl=file:///mnt/
gpgcheck=0
enabled=1
https://bugzilla.redhat.com/show_bug.cgi?id=1748841
---
dnf/conf/read.py | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/dnf/conf/read.py b/dnf/conf/read.py
index a526a71..1efac22 100644
--- a/dnf/conf/read.py
+++ b/dnf/conf/read.py
@@ -43,7 +43,7 @@ class RepoReader(object):
# read .repo files from directories specified by conf.reposdir
for repofn in (repofn for reposdir in self.conf.reposdir
- for repofn in sorted(glob.glob('%s/*.repo' % reposdir))):
+ for repofn in sorted(glob.glob('{}/*.repo'.format(reposdir)))):
try:
for r in self._get_repos(repofn):
yield r
@@ -54,17 +54,38 @@ class RepoReader(object):
def _build_repo(self, parser, id_, repofn):
"""Build a repository using the parsed data."""
- repo = dnf.repo.Repo(id_, self.conf)
+ substituted_id = libdnf.conf.ConfigParser.substitute(id_, self.conf.substitutions)
+
+ # Check the repo.id against the valid chars
+ invalid = dnf.repo.repo_id_invalid(substituted_id)
+ if invalid is not None:
+ if substituted_id != id_:
+ msg = _("Bad id for repo: {} ({}), byte = {} {}").format(substituted_id, id_,
+ substituted_id[invalid],
+ invalid)
+ else:
+ msg = _("Bad id for repo: {}, byte = {} {}").format(id_, id_[invalid], invalid)
+ raise dnf.exceptions.ConfigError(msg)
+
+ repo = dnf.repo.Repo(substituted_id, self.conf)
try:
repo._populate(parser, id_, repofn, dnf.conf.PRIO_REPOCONFIG)
except ValueError as e:
- msg = _("Repository '%s': Error parsing config: %s") % (id_, e)
+ if substituted_id != id_:
+ msg = _("Repository '{}' ({}): Error parsing config: {}").format(substituted_id,
+ id_, e)
+ else:
+ msg = _("Repository '{}': Error parsing config: {}").format(id_, e)
raise dnf.exceptions.ConfigError(msg)
# Ensure that the repo name is set
if repo._get_priority('name') == dnf.conf.PRIO_DEFAULT:
- msg = _("Repository '%s' is missing name in configuration, using id.")
- logger.warning(msg, id_)
+ if substituted_id != id_:
+ msg = _("Repository '{}' ({}) is missing name in configuration, using id.").format(
+ substituted_id, id_)
+ else:
+ msg = _("Repository '{}' is missing name in configuration, using id.").format(id_)
+ logger.warning(msg)
repo.name = ucd(repo.name)
repo._substitutions.update(self.conf.substitutions)
repo.cfg = parser
@@ -80,23 +101,16 @@ class RepoReader(object):
try:
parser.read(repofn)
except RuntimeError as e:
- raise dnf.exceptions.ConfigError(_('Parsing file "%s" failed: %s') % (repofn, e))
+ raise dnf.exceptions.ConfigError(_('Parsing file "{}" failed: {}').format(repofn, e))
except IOError as e:
logger.warning(e)
# Check sections in the .repo file that was just slurped up
for section in parser.getData():
if section == 'main':
continue
- # Check the repo.id against the valid chars
- invalid = dnf.repo.repo_id_invalid(section)
- if invalid is not None:
- logger.warning(_("Bad id for repo: %s, byte = %s %d"), section,
- section[invalid], invalid)
- continue
-
try:
thisrepo = self._build_repo(parser, ucd(section), repofn)
except (dnf.exceptions.RepoError, dnf.exceptions.ConfigError) as e:
--
libgit2 0.28.2

View File

@ -0,0 +1,67 @@
From ba3615c600532a0ce8693a626a9cbe71a458399a Mon Sep 17 00:00:00 2001
From: Pavla Kratochvilova <pkratoch@redhat.com>
Date: Thu, 23 May 2019 14:48:29 +0200
Subject: [PATCH 1/2] Respect order of config files in aliases.d
(RhBug:1680489)
https://bugzilla.redhat.com/show_bug.cgi?id=1680489
The aliases config files were read in arbitrary order (os.listdir does not
give sorted output). It is better to define clear order (i.e. all config files
except USER.conf are ordered alphabetically, USER.conf is the last).
Closes: #1542
Approved by: kontura
---
dnf/cli/aliases.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dnf/cli/aliases.py b/dnf/cli/aliases.py
index 0b3ba8f6b..b5283d0f3 100644
--- a/dnf/cli/aliases.py
+++ b/dnf/cli/aliases.py
@@ -143,7 +143,7 @@ class Aliases(object):
try:
if not os.path.exists(ALIASES_DROPIN_DIR):
os.mkdir(ALIASES_DROPIN_DIR)
- for fn in os.listdir(ALIASES_DROPIN_DIR):
+ for fn in sorted(os.listdir(ALIASES_DROPIN_DIR)):
if _ignore_filename(fn):
continue
filenames.append(os.path.join(ALIASES_DROPIN_DIR, fn))
--
2.21.0
From e292de84fcdec844530099a6c37ef29e1a330003 Mon Sep 17 00:00:00 2001
From: Pavla Kratochvilova <pkratoch@redhat.com>
Date: Thu, 23 May 2019 15:04:34 +0200
Subject: [PATCH 2/2] [doc] Describe priorities of config files in aliases.d
(RhBug:1680489)
https://bugzilla.redhat.com/show_bug.cgi?id=1680489
Closes: #1542
Approved by: kontura
---
doc/command_ref.rst | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
index 7141fc2aa..637ccf96b 100644
--- a/doc/command_ref.rst
+++ b/doc/command_ref.rst
@@ -424,7 +424,10 @@ for aliases. The alias processing stops when the first found command is not a na
Also, like in shell aliases, if the result starts with a ``\``, the alias processing will stop.
All aliases are defined in configuration files in the ``/etc/dnf/aliases.d/`` directory in the [aliases] section,
-and aliases created by the alias command are written to the ``USER.conf`` file.
+and aliases created by the alias command are written to the ``USER.conf`` file. In case of conflicts,
+the ``USER.conf`` has the highest priority, and alphabetical ordering is used for the rest of the
+configuration files.
+
Optionally, there is the ``enabled`` option in the ``[main]`` section defaulting to True. This can be set for each
file separately in the respective file, or globally for all aliases in the ``ALIASES.conf`` file.
--
2.21.0

View File

@ -1,118 +0,0 @@
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,32 @@
From 3c473306e5e1b630a3030791fb1ef7ea0c0cd823 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Tue, 26 Nov 2019 13:22:15 +0100
Subject: [PATCH] [doc] Remove note about whitelist
The whitelist mechanism has been recently removed from libdnf.
Closes: #1543
Approved by: Conan-Kudo
---
doc/conf_ref.rst | 5 -----
1 file changed, 5 deletions(-)
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
index d3ea11d..cb95e47 100644
--- a/doc/conf_ref.rst
+++ b/doc/conf_ref.rst
@@ -806,11 +806,6 @@ configuration.
libdnf (Fedora 31; server; Linux.x86_64)
- To avoid leaking identifiable data, the variant in the above string will be
- replaced by "generic" if the value is not an official Fedora variant.
- Likewise, the whole OS part (enclosed in parenthesis) will be omitted if
- this is a non-Fedora system.
-
=================
Types of Options
=================
--
libgit2 0.28.2

View File

@ -0,0 +1,157 @@
From c8d79c0b9956aeeb8cd3a0422656b030d4656578 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Mon, 9 Dec 2019 12:32:18 +0100
Subject: [PATCH 1/2] Fix detection of the latest module (RhBug:1781769)
The code originally compared module version as a string, but it should
be compared as a int.
https://bugzilla.redhat.com/show_bug.cgi?id=1781769
Closes: #1548
Approved by: m-blaha
---
dnf/module/module_base.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dnf/module/module_base.py b/dnf/module/module_base.py
index 8093ab443..64bad84b6 100644
--- a/dnf/module/module_base.py
+++ b/dnf/module/module_base.py
@@ -285,7 +285,7 @@ class ModuleBase(object):
if module_list:
latest = module_list[0]
for module in module_list[1:]:
- if module.getVersion() > latest.getVersion():
+ if module.getVersionNum() > latest.getVersionNum():
latest = module
return latest
--
2.21.0
From 44e9095404569dbf8a19726eb79be8e580bed60c Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Wed, 11 Dec 2019 09:52:16 +0100
Subject: [PATCH 2/2] Improve transaction table formatting
It improves formatting of transaction table in case when terminal has
unknown width.
Closes: #1548
Approved by: m-blaha
---
dnf/cli/output.py | 45 ++++++++++++++++++++++++---------------------
1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
index a03df610c..2ff41b625 100644
--- a/dnf/cli/output.py
+++ b/dnf/cli/output.py
@@ -224,16 +224,32 @@ class Output(object):
if total_width is None:
total_width = self.term.real_columns
+ # We start allocating 1 char to everything but the last column, and a
+ # space between each (again, except for the last column). Because
+ # at worst we are better with:
+ # |one two three|
+ # | four |
+ # ...than:
+ # |one two three|
+ # | f|
+ # |our |
+ # ...the later being what we get if we pre-allocate the last column, and
+ # thus. the space, due to "three" overflowing it's column by 2 chars.
+ if columns is None:
+ columns = [1] * (cols - 1)
+ columns.append(0)
+
# i'm not able to get real terminal width so i'm probably
# running in non interactive terminal (pipe to grep, redirect to file...)
# avoid splitting lines to enable filtering output
if not total_width:
full_columns = []
- for col in data:
+ for d in xrange(0, cols):
+ col = data[d]
if col:
full_columns.append(col[-1][0])
else:
- full_columns.append(0)
+ full_columns.append(columns[d] + 1)
full_columns[0] += len(indent)
# if possible, try to keep default width (usually 80 columns)
default_width = self.term.columns
@@ -241,20 +257,6 @@ class Output(object):
return full_columns
total_width = default_width
- # We start allocating 1 char to everything but the last column, and a
- # space between each (again, except for the last column). Because
- # at worst we are better with:
- # |one two three|
- # | four |
- # ...than:
- # |one two three|
- # | f|
- # |our |
- # ...the later being what we get if we pre-allocate the last column, and
- # thus. the space, due to "three" overflowing it's column by 2 chars.
- if columns is None:
- columns = [1] * (cols - 1)
- columns.append(0)
total_width -= (sum(columns) + (cols - 1) + exact_width(indent))
if not columns[-1]:
@@ -1273,7 +1275,7 @@ class Output(object):
skip_str = skip_str % _(" or part of a group")
pkglist_lines.append((skip_str, lines))
-
+ output_width = self.term.columns
if not data['n'] and not self.base._moduleContainer.isChanged() and not \
(self.base._history and (self.base._history.group or self.base._history.env)):
return u''
@@ -1283,6 +1285,8 @@ class Output(object):
columns = self.calcColumns(data, indent=" ", columns=columns,
remainder_column=2, total_width=total_width)
(n_wid, a_wid, v_wid, r_wid, s_wid) = columns
+ real_width = sum(columns) + 5
+ output_width = output_width if output_width >= real_width else real_width
# Do not use 'Package' without context. Using context resolves
# RhBug 1302935 as a side effect.
@@ -1325,13 +1329,13 @@ class Output(object):
# Translators: This is the full (unabbreviated) term 'Size'.
C_('long', 'Size'))
- out = [u"%s\n%s\n%s\n" % ('=' * self.term.columns,
+ out = [u"%s\n%s\n%s\n" % ('=' * output_width,
self.fmtColumns(((msg_package, -n_wid),
(msg_arch, -a_wid),
(msg_version, -v_wid),
(msg_repository, -r_wid),
(msg_size, s_wid)), u" "),
- '=' * self.term.columns)]
+ '=' * output_width)]
for (action, lines) in pkglist_lines:
if lines:
@@ -1349,11 +1353,10 @@ class Output(object):
if lines:
out.append(totalmsg)
-
out.append(_("""
Transaction Summary
%s
-""") % ('=' * self.term.columns))
+""") % ('=' * output_width))
summary_data = (
(_('Install'), len(list_bunch.installed) +
len(list_bunch.installed_group) +
--
2.21.0

View File

@ -1,99 +0,0 @@
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

@ -1,435 +0,0 @@
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,106 @@
From 4c2f0dbd2ffecec35c9df09190a5eeb8c4abce73 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Fri, 22 Nov 2019 08:02:45 +0100
Subject: [PATCH 1/2] Remove misleading comments
---
dnf/cli/cli.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
index 80df950c8d..9fbe7d3ada 100644
--- a/dnf/cli/cli.py
+++ b/dnf/cli/cli.py
@@ -405,13 +405,9 @@ def downgradePkgs(self, specs=[], file_pkgs=[], strict=False):
for pkg in file_pkgs:
try:
self.package_downgrade(pkg, strict=strict)
- continue # it was something on disk and it ended in rpm
- # no matter what we don't go looking at repos
except dnf.exceptions.MarkingError as e:
logger.info(_('No match for argument: %s'),
self.output.term.bold(pkg.location))
- # it was something on disk and it ended in rpm
- # no matter what we don't go looking at repos
for arg in specs:
try:
From 09b035f5d71c86b88da2d6ea117282fab5e87caa Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Tue, 19 Nov 2019 07:08:21 +0100
Subject: [PATCH 2/2] Unify downgrade exit codes with upgrade (RhBug:1759847)
Now the dnf downgrade/upgrade commands behave consistently
in case the lowest/highest available version was already
installed. On top of that the behaviour is now compatible with
yum-3.
Behaviour of upgrade command in case that the latest version of
acpi is already installed:
$ dnf upgrade acpi
Dependencies resolved.
Nothing to do.
Complete!
The exit code of dnf upgrade is 0
In case that the lowest version of acpi is installed:
Previous behaviour:
$ dnf downgrade acpi
Package acpi of lowest version already installed, cannot downgrade it.
Error: No packages marked for downgrade.
The exit code of dnf downgrade was 1
New behaviour:
$ dnf downgrade acpi
Package acpi of lowest version already installed, cannot downgrade it.
Dependencies resolved.
Nothing to do.
Complete!
The exit code of dnf downgrade is 0
https://bugzilla.redhat.com/show_bug.cgi?id=1759847
---
dnf/cli/cli.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
index 9fbe7d3ada..7a8d9e3b27 100644
--- a/dnf/cli/cli.py
+++ b/dnf/cli/cli.py
@@ -401,10 +401,11 @@ def downgradePkgs(self, specs=[], file_pkgs=[], strict=False):
:param file_pkgs: a list of pkg objects from local files
"""
- oldcount = self._goal.req_length()
+ result = False
for pkg in file_pkgs:
try:
self.package_downgrade(pkg, strict=strict)
+ result = True
except dnf.exceptions.MarkingError as e:
logger.info(_('No match for argument: %s'),
self.output.term.bold(pkg.location))
@@ -412,6 +413,7 @@ def downgradePkgs(self, specs=[], file_pkgs=[], strict=False):
for arg in specs:
try:
self.downgrade_to(arg, strict=strict)
+ result = True
except dnf.exceptions.PackageNotFoundError as err:
msg = _('No package %s available.')
logger.info(msg, self.output.term.bold(arg))
@@ -420,8 +422,8 @@ def downgradePkgs(self, specs=[], file_pkgs=[], strict=False):
self.output.term.bold(err.pkg_spec))
except dnf.exceptions.MarkingError:
assert False
- cnt = self._goal.req_length() - oldcount
- if cnt <= 0:
+
+ if not result:
raise dnf.exceptions.Error(_('No packages marked for downgrade.'))
def output_packages(self, basecmd, pkgnarrow='all', patterns=(), reponame=None):

View File

@ -1,82 +0,0 @@
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,125 @@
From ee670a94b7f53716ac8db4a7ee1723d886378d6f Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Fri, 22 Nov 2019 18:24:37 +0100
Subject: [PATCH 1/3] Restore functionality of remove --oldinstallonly
Additionally it also starts to protect running kernel.
https://bugzilla.redhat.com/show_bug.cgi?id=1774666
---
dnf/cli/commands/remove.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/dnf/cli/commands/remove.py b/dnf/cli/commands/remove.py
index f8059e4634..7b53dafcc4 100644
--- a/dnf/cli/commands/remove.py
+++ b/dnf/cli/commands/remove.py
@@ -110,8 +110,14 @@ def run(self):
if self.opts.oldinstallonly:
q = self.base.sack.query()
- instonly = self.base._get_installonly_query(q.installed()).latest(
- - self.base.conf.installonly_limit)
+ instonly = self.base._get_installonly_query(q.installed()).latest(-1)
+ # also remove running kernel from the set
+ kernel = self.base.sack.get_running_kernel()
+ if kernel is not None:
+ running_installonly = instonly.filter(
+ epoch=kernel.epoch, version=kernel.version, release=kernel.release)
+ if running_installonly:
+ instonly = instonly.difference(running_installonly)
if instonly:
for pkg in instonly:
self.base.package_remove(pkg)
From 031b424e3cf944f7585308ddda024ca6d2031c08 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Fri, 6 Dec 2019 13:50:37 +0100
Subject: [PATCH 2/3] Keep installed packages in upgrade transaction
In some cases missing installed packages could lead in an alternative
decision.
---
dnf/base.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/dnf/base.py b/dnf/base.py
index 8091ca0366..f9d31b3f34 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -1975,17 +1975,19 @@ def package_upgrade(self, pkg):
return 0
def _upgrade_internal(self, query, obsoletes, reponame, pkg_spec=None):
- installed = self.sack.query().installed()
- q = query.intersection(self.sack.query().filterm(name=[pkg.name for pkg in installed]))
+ installed_all = self.sack.query().installed()
+ q = query.intersection(self.sack.query().filterm(name=[pkg.name for pkg in installed_all]))
+ installed_query = q.installed()
if obsoletes:
obsoletes = self.sack.query().available().filterm(
- obsoletes=q.installed().union(q.upgrades()))
+ obsoletes=installed_query.union(q.upgrades()))
# add obsoletes into transaction
q = q.union(obsoletes)
if reponame is not None:
q.filterm(reponame=reponame)
q = self._merge_update_filters(q, pkg_spec=pkg_spec)
if q:
+ q = q.available().union(installed_query.latest())
sltr = dnf.selector.Selector(self.sack)
sltr.set(pkg=q)
self._goal.upgrade(select=sltr)
From 7cba81e129944b8b610895d24df1c4dbaa23b6a1 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Fri, 6 Dec 2019 13:51:11 +0100
Subject: [PATCH 3/3] [doc] Update documentation of remove --oldinstallonly
---
doc/cli_vs_yum.rst | 18 +++++++++---------
doc/command_ref.rst | 2 +-
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/doc/cli_vs_yum.rst b/doc/cli_vs_yum.rst
index 56945869c9..bb379ab03e 100644
--- a/doc/cli_vs_yum.rst
+++ b/doc/cli_vs_yum.rst
@@ -387,15 +387,15 @@ Original YUM tool New DNF command Pack
Detailed table for ``package-cleanup`` replacement:
-================================== =====================================
-``package-cleanup --dupes`` ``dnf repoquery --duplicates``
-``package-cleanup --leaves`` ``dnf repoquery --unneeded``
-``package-cleanup --orphans`` ``dnf repoquery --extras``
-``package-cleanup --oldkernels`` ``dnf repoquery --installonly``
-``package-cleanup --problems`` ``dnf repoquery --unsatisfied``
-``package-cleanup --cleandupes`` ``dnf remove --duplicates``
-``package-cleanup --oldkernels`` ``dnf remove --oldinstallonly``
-================================== =====================================
+========================================== ===============================================================
+``package-cleanup --dupes`` ``dnf repoquery --duplicates``
+``package-cleanup --leaves`` ``dnf repoquery --unneeded``
+``package-cleanup --orphans`` ``dnf repoquery --extras``
+``package-cleanup --problems`` ``dnf repoquery --unsatisfied``
+``package-cleanup --cleandupes`` ``dnf remove --duplicates``
+``package-cleanup --oldkernels`` ``dnf remove --oldinstallonly``
+``package-cleanup --oldkernels --keep=2`` ``dnf remove $(dnf repoquery --installonly --latest-limit=-2)``
+========================================== ===============================================================
=============================
yum-updateonboot and yum-cron
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
index 7141fc2aae..134cc3d546 100644
--- a/doc/command_ref.rst
+++ b/doc/command_ref.rst
@@ -1061,7 +1061,7 @@ Remove Command
dnf-shell sub-commands could help.
``dnf [options] remove --oldinstallonly``
- Removes old installonly packages, keeping only ``installonly_limit`` latest versions.
+ Removes old installonly packages, keeping only latest versions and version of running kernel.
There are also a few specific remove commands ``remove-n``, ``remove-na`` and ``remove-nevra``
that allow the specification of an exact argument in the NEVRA format.

View File

@ -1,93 +0,0 @@
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,111 @@
From 2e78e3006ca8b640028b98afd2ccaa5d26ead7e3 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 3 Dec 2019 09:09:20 +0100
Subject: [PATCH 1/3] [doc] Add note about limitation of the shell command
---
doc/command_ref.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
index 24e08efdb2..cc27f57bba 100644
--- a/doc/command_ref.rst
+++ b/doc/command_ref.rst
@@ -1515,6 +1515,11 @@ Shell Command
* reset: reset the transaction
* run: resolve and run the transaction
+ Note that all local packages must be used in the first shell transaction subcommand (e.g.
+ `install /tmp/nodejs-1-1.x86_64.rpm /tmp/acpi-1-1.noarch.rpm`) otherwise an error will occur.
+ Any `disable`, `enable`, and `reset` module operations (e.g. `module enable nodejs`) must also
+ be performed before any other shell transaction subcommand is used.
+
.. _swap_command-label:
------------
From 9e1958f3695b50f3c49f9aa2a8a113bbf660d62c Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 3 Dec 2019 09:31:49 +0100
Subject: [PATCH 2/3] Prevent adding remote packages when goal is not empty
(RhBug:1773483)
Adding remote packages by add_remote_rpms() when goal is not empty
results in transaction that is completely broken, because elements in
transaction get different meaning.
https://bugzilla.redhat.com/show_bug.cgi?id=1773483
---
dnf/base.py | 3 +++
tests/test_base.py | 1 +
2 files changed, 4 insertions(+)
diff --git a/dnf/base.py b/dnf/base.py
index 8091ca0366..c4ea04181a 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -1162,6 +1162,9 @@ def add_remote_rpms(self, path_list, strict=True, progress=None):
pkgs = []
if not path_list:
return pkgs
+ if self._goal.req_length():
+ raise dnf.exceptions.Error(
+ _("Cannot add local packages, because transaction job already exists"))
pkgs_error = []
for path in path_list:
if not os.path.exists(path) and '://' in path:
diff --git a/tests/test_base.py b/tests/test_base.py
index 0d50516d2f..8f807b7c13 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -168,6 +168,7 @@ class MockBaseTest(tests.support.DnfBaseTestCase):
"""Test the Base methods that need a Sack."""
REPOS = ["main"]
+ INIT_SACK = True
def test_add_remote_rpms(self):
pkgs = self.base.add_remote_rpms([tests.support.TOUR_50_PKG_PATH])
From 575ef19433909d3bf7d90e5e4b36f912a472b517 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Wed, 4 Dec 2019 13:17:26 +0100
Subject: [PATCH 3/3] [doc] Describe the new behavior of Base.add_remote_rpms()
---
doc/api_base.rst | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/doc/api_base.rst b/doc/api_base.rst
index 5fd5b4cc99..618886d0cd 100644
--- a/doc/api_base.rst
+++ b/doc/api_base.rst
@@ -33,6 +33,10 @@
An instance of :class:`dnf.conf.Conf`, concentrates all the different configuration options. :meth:`__init__` initializes this to usable defaults.
+ .. attribute:: goal
+
+ An instance of :class:`dnf.goal.Goal` that this :class:`Base<dnf.Base>` object is using.
+
.. attribute:: repos
A :class:`dnf.repodict.RepoDict` instance, this member object contains all the repositories available.
@@ -51,11 +55,12 @@
.. method:: add_remote_rpms(path_list, strict=True, progress=None)
- Add RPM files at list `path_list` to the :attr:`sack` and return the list of respective
- :class:`dnf.package.Package` instances. Does the download to a temporary files for each path if
- `path` is a remote URL. Raises :exc:`IOError` if there are problems obtaining during reading
- files and `strict=True`. `progress`, if given, should be a :class:`.DownloadProgress` and can be
- used by the caller to monitor the progress of the download.
+ This function must be called before anything is added to the :attr:`goal`. Adds RPM files
+ in path_list to the :attr:`sack` and return the list of respective :class:`dnf.package.Package`
+ instances. Downloads the RPMs to a temporary file for each path if it is a remote URL.
+ Raises :exc:`IOError` if there are `IO` problems with files and `strict=True`. Raises
+ :exc:`dnf.exceptions.Error` if the :attr:`goal` is not empty. `progress`, if given, should be a
+ :class:`.DownloadProgress` instance which can be used to monitor the progress of the download.
.. method:: close()

View File

@ -0,0 +1,115 @@
From 27d2957e5051cc2edbea3a0d28a630e7eabfd673 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Fri, 6 Dec 2019 09:19:11 +0100
Subject: [PATCH] Improve help for 'dnf module' command (RhBug:1758447)
Added short summary for each subcommand of the 'dnf module' command.
https://bugzilla.redhat.com/show_bug.cgi?id=1758447
---
dnf/cli/commands/module.py | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/dnf/cli/commands/module.py b/dnf/cli/commands/module.py
index 07883af6a3..5a6c0069fb 100644
--- a/dnf/cli/commands/module.py
+++ b/dnf/cli/commands/module.py
@@ -74,6 +74,7 @@ def _get_module_artifact_names(self, use_modules, skip_modules):
class ListSubCommand(SubCommand):
aliases = ('list',)
+ summary = _('list all module streams, profiles and states')
def configure(self):
demands = self.cli.demands
@@ -107,6 +108,7 @@ def run_on_module(self):
class InfoSubCommand(SubCommand):
aliases = ('info',)
+ summary = _('print detailed information about a module')
def configure(self):
demands = self.cli.demands
@@ -128,6 +130,7 @@ def run_on_module(self):
class EnableSubCommand(SubCommand):
aliases = ('enable',)
+ summary = _('enable a module stream')
def configure(self):
demands = self.cli.demands
@@ -151,6 +154,7 @@ def run_on_module(self):
class DisableSubCommand(SubCommand):
aliases = ('disable',)
+ summary = _('disable a module with all its streams')
def configure(self):
demands = self.cli.demands
@@ -174,6 +178,7 @@ def run_on_module(self):
class ResetSubCommand(SubCommand):
aliases = ('reset',)
+ summary = _('reset a module')
def configure(self):
demands = self.cli.demands
@@ -194,6 +199,7 @@ def run_on_module(self):
class InstallSubCommand(SubCommand):
aliases = ('install',)
+ summary = _('install a module profile including its packages')
def configure(self):
demands = self.cli.demands
@@ -214,6 +220,7 @@ def run_on_module(self):
class UpdateSubCommand(SubCommand):
aliases = ('update',)
+ summary = _('update packages associated with an active stream')
def configure(self):
demands = self.cli.demands
@@ -230,6 +237,7 @@ def run_on_module(self):
class RemoveSubCommand(SubCommand):
aliases = ('remove', 'erase',)
+ summary = _('remove installed module profiles and their packages')
def configure(self):
demands = self.cli.demands
@@ -266,6 +274,7 @@ def run_on_module(self):
class ProvidesSubCommand(SubCommand):
aliases = ("provides", )
+ summary = _('list modular packages')
def configure(self):
demands = self.cli.demands
@@ -280,6 +289,7 @@ def run_on_module(self):
class RepoquerySubCommand(SubCommand):
aliases = ("repoquery", )
+ summary = _('list packages belonging to a module')
def configure(self):
demands = self.cli.demands
@@ -342,10 +352,14 @@ def set_argparser(self, parser):
narrows.add_argument('--all', dest='all',
action='store_true',
help=_("remove all modular packages"))
-
- subcommand_help = [subcmd.aliases[0] for subcmd in self.SUBCMDS]
- parser.add_argument('subcmd', nargs=1, choices=subcommand_help,
- help=_("Modular command"))
+ subcommand_choices = []
+ subcommand_help = []
+ for subcmd in sorted(self.SUBCMDS, key=lambda x: x.aliases[0]):
+ subcommand_choices.append(subcmd.aliases[0])
+ subcommand_help.append('{}: {}'.format(subcmd.aliases[0], subcmd.summary or ''))
+ parser.add_argument('subcmd', nargs=1, choices=subcommand_choices,
+ metavar='<modular command>',
+ help='\n'.join(subcommand_help))
parser.add_argument('module_spec', metavar='module-spec', nargs='*',
help=_("Module specification"))

View File

@ -1,33 +0,0 @@
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,33 @@
From 32f331724cc8b473073fa0f29ad93044b1dde824 Mon Sep 17 00:00:00 2001
From: Brandon Bennett <bennetb@gmail.com>
Date: Mon, 16 Dec 2019 09:37:24 -0700
Subject: [PATCH] Strip '\' from aliases when processing (RhBug:1680482)
de40e3f7e910d5533dfbcc377807caaae115ed3e reworked the alias resolution
to detect infinate recursion, however it broke how the '\' works during
resolution. Before the '\\' was stripped but now it is no longer.
This just adds a check to see if '\\' is in the first part of the
arguments and strips it.
---
dnf/cli/aliases.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/dnf/cli/aliases.py b/dnf/cli/aliases.py
index b5283d0f33..364aab6d21 100644
--- a/dnf/cli/aliases.py
+++ b/dnf/cli/aliases.py
@@ -176,8 +176,13 @@ def subresolve(args):
suffix[0].startswith('\\')): # End resolving
try:
stack.pop()
+
+ # strip the '\' if it exists
+ if suffix[0].startswith('\\'):
+ suffix[0] = suffix[0][1:]
except IndexError:
pass
+
return suffix
if suffix[0] in stack: # Infinite recursion detected

View File

@ -1,45 +0,0 @@
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

@ -1,33 +0,0 @@
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,61 @@
From 505e534817d076c5190b211983a8a2c930cbe560 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Mon, 16 Dec 2019 11:14:33 +0100
Subject: [PATCH] Honor priority with check-update (RhBug:1769466)
Check update is going to use the new query filter that honors repo
priority.
https://bugzilla.redhat.com/show_bug.cgi?id=1769466
---
dnf.spec | 2 +-
dnf/base.py | 4 ++--
dnf/cli/commands/__init__.py | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dnf.spec b/dnf.spec
index e20be1e241..57bfd778d4 100644
--- a/dnf.spec
+++ b/dnf.spec
@@ -1,5 +1,5 @@
# default dependencies
-%global hawkey_version 0.39.1
+%global hawkey_version 0.41.0
%global libcomps_version 0.1.8
%global libmodulemd_version 1.4.0
%global rpm_version 4.14.0
diff --git a/dnf/base.py b/dnf/base.py
index c4ea04181a..1ed01c37a9 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -1365,7 +1365,7 @@ def query_for_repo(query):
# produce the updates list of tuples
elif pkgnarrow == 'upgrades':
- updates = query_for_repo(q).upgrades()
+ updates = query_for_repo(q).filterm(upgrades_by_priority=True)
# reduce a query to security upgrades if they are specified
updates = self._merge_update_filters(updates)
# reduce a query to latest packages
@@ -1417,7 +1417,7 @@ def query_for_repo(query):
elif pkgnarrow == 'obsoletes':
inst = q.installed()
obsoletes = query_for_repo(
- self.sack.query()).filter(obsoletes=inst)
+ self.sack.query()).filter(obsoletes_by_priority=inst)
# reduce a query to security upgrades if they are specified
obsoletes = self._merge_update_filters(obsoletes, warning=False)
obsoletesTuples = []
diff --git a/dnf/cli/commands/__init__.py b/dnf/cli/commands/__init__.py
index 2a0726b654..d71a97f910 100644
--- a/dnf/cli/commands/__init__.py
+++ b/dnf/cli/commands/__init__.py
@@ -279,7 +279,7 @@ def configure(self):
_checkEnabledRepo(self.base)
def run(self):
- query = self.base.sack.query().upgrades()
+ query = self.base.sack.query().filterm(upgrades_by_priority=True)
if self.base.conf.obsoletes:
obsoleted = query.union(self.base.sack.query().installed())
obsoletes = self.base.sack.query().filter(obsoletes=obsoleted)

View File

@ -0,0 +1,50 @@
From f89ac56ef0ee7a349e0389913a510ba194022e95 Mon Sep 17 00:00:00 2001
From: Pavla Kratochvilova <pkratoch@redhat.com>
Date: Thu, 23 May 2019 14:32:32 +0200
Subject: [PATCH 1/2] Print the whole alias definition in case of infinite
recursion (RhBug:1680488)
https://bugzilla.redhat.com/show_bug.cgi?id=1680488
---
dnf/cli/commands/alias.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dnf/cli/commands/alias.py b/dnf/cli/commands/alias.py
index 10f58867ca..d3e6e4326e 100644
--- a/dnf/cli/commands/alias.py
+++ b/dnf/cli/commands/alias.py
@@ -151,7 +151,8 @@ def list_alias(self, cmd):
try:
args = self.aliases_base._resolve(args)
except dnf.exceptions.Error as e:
- logger.error(_('%s, alias %s'), e, cmd)
+ logger.error(
+ _('%s, alias %s="%s"'), e, cmd, (' ').join(self.aliases_base.aliases[cmd]))
else:
print(_("Alias %s='%s'") % (cmd, " ".join(args)))
From ccd4213da366d49f6f84847fa2ccdb890d257930 Mon Sep 17 00:00:00 2001
From: Pavla Kratochvilova <pkratoch@redhat.com>
Date: Thu, 23 May 2019 14:39:19 +0200
Subject: [PATCH 2/2] [doc] Document aliases behavior in case of infinite
recursion (RhBug:1680488)
https://bugzilla.redhat.com/show_bug.cgi?id=1680488
---
doc/command_ref.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
index ba22453055..ab72b66f8f 100644
--- a/doc/command_ref.rst
+++ b/doc/command_ref.rst
@@ -423,6 +423,8 @@ To use an alias (name=value), the name must be placed as the first "command" (e.
that is not an option). It is then replaced by its value and the resulting sequence is again searched
for aliases. The alias processing stops when the first found command is not a name of any alias.
+In case the processing would result in an infinite recursion, the original arguments are used instead.
+
Also, like in shell aliases, if the result starts with a ``\``, the alias processing will stop.
All aliases are defined in configuration files in the ``/etc/dnf/aliases.d/`` directory in the [aliases] section,

View File

@ -1,49 +0,0 @@
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

View File

@ -0,0 +1,32 @@
From 3a332e3eba6230d7da7472db654d50b8070570d8 Mon Sep 17 00:00:00 2001
From: Pavla Kratochvilova <pkratoch@redhat.com>
Date: Thu, 23 May 2019 11:07:37 +0200
Subject: [PATCH] [doc] Explain the backslash notation also near the example
(RhBug:1680482)
https://bugzilla.redhat.com/show_bug.cgi?id=1680482
The backslash notation is mentioned before, but this adds an explanation
directly to the example where it is used.
---
doc/command_ref.rst | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
index ba22453055..84bad4b2b3 100644
--- a/doc/command_ref.rst
+++ b/doc/command_ref.rst
@@ -454,10 +454,12 @@ Alias Examples
Lists all defined aliases.
``dnf alias add rm=remove``
- Adds new alias command called "rm" which does the same thing as the command "remove".
+ Adds a new command alias called ``rm`` which works the same as the ``remove`` command.
``dnf alias add update="\update --skip-broken --disableexcludes=all --obsoletes"``
- Adds new alias command called "update" which does the same thing as the command "update", but with options ``--skip-broken --disableexcludes=all --obsoletes``.
+ Adds a new command alias called ``update`` which works the same as the ``update`` command,
+ with additional options. Note that the original ``update`` command is prefixed with a ``\``
+ to prevent an infinite loop in alias processing.
.. _alias_processing_examples-label:

View File

@ -0,0 +1,82 @@
From fa6afad083ffc19438603f43d17785f5741505b4 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Mon, 16 Dec 2019 12:52:41 +0100
Subject: [PATCH 1/2] Sort packages in transaction output by nevra
(RhBug:1773436)
---
dnf/cli/output.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
index 2ff41b6255..1d3eb1e94a 100644
--- a/dnf/cli/output.py
+++ b/dnf/cli/output.py
@@ -1147,7 +1147,7 @@ def _add_line(lines, data, a_wid, po, obsoletes=[]):
for i in tsi._item.getReplacedBy():
replaces.setdefault(i, set()).add(tsi)
- for tsi in pkglist:
+ for tsi in sorted(pkglist, key=lambda x: x.pkg):
if tsi.action not in dnf.transaction.FORWARD_ACTIONS + [libdnf.transaction.TransactionItemAction_REMOVE]:
continue
From 0779b458ca30e895b72bcfb2d513c13b12f605df Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Mon, 16 Dec 2019 14:53:00 +0100
Subject: [PATCH 2/2] Sort packages in post transaction output by nevra
---
dnf/cli/output.py | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
index 1d3eb1e94a..5dc0af6f4b 100644
--- a/dnf/cli/output.py
+++ b/dnf/cli/output.py
@@ -23,6 +23,7 @@
from copy import deepcopy
import fnmatch
+import functools
import hawkey
import itertools
import libdnf.transaction
@@ -1449,11 +1450,26 @@ 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, self.base._goal)
skipped_conflicts, skipped_broken = self._skipped_packages(report_problems=False)
skipped = skipped_conflicts.union(skipped_broken)
- skipped = sorted(set([str(pkg) for pkg in skipped]))
for (action, tsis) in [(_('Upgraded'), list_bunch.upgraded),
(_('Downgraded'), list_bunch.downgraded),
@@ -1471,7 +1487,7 @@ def _fits_in_cols(msgs, num):
continue
msgs = []
out += '\n%s:\n' % action
- for tsi in tsis:
+ 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)

View File

@ -0,0 +1,57 @@
From bcfb9e8998a87f5737b6dbce5edd206f56d732eb Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Fri, 3 Jan 2020 10:57:59 +0100
Subject: [PATCH] Add support of commandline packages in repoquery
(RhBug:1784148)
https://bugzilla.redhat.com/show_bug.cgi?id=1784148
---
dnf/cli/commands/repoquery.py | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/dnf/cli/commands/repoquery.py b/dnf/cli/commands/repoquery.py
index f5cb36fe57..7334ddcd90 100644
--- a/dnf/cli/commands/repoquery.py
+++ b/dnf/cli/commands/repoquery.py
@@ -402,6 +402,20 @@ def _get_recursive_providers_query(self, query_in, providers, done=None):
done = self._get_recursive_providers_query(query_in, query_select, done=t.union(done))
return t.union(done)
+ def _add_add_remote_packages(self):
+ rpmnames = []
+ remote_packages = []
+ for key in self.opts.key:
+ schemes = dnf.pycomp.urlparse.urlparse(key)[0]
+ if key.endswith('.rpm'):
+ rpmnames.append(key)
+ elif schemes and schemes in ('http', 'ftp', 'file', 'https'):
+ rpmnames.append(key)
+ if rpmnames:
+ remote_packages = self.base.add_remote_rpms(
+ rpmnames, strict=False, progress=self.base.output.progress)
+ return remote_packages
+
def run(self):
if self.opts.querytags:
print(_('Available query-tags: use --queryformat ".. %{tag} .."'))
@@ -416,6 +430,8 @@ def run(self):
else hawkey.APPLY_EXCLUDES
)
if self.opts.key:
+ remote_packages = self._add_add_remote_packages()
+
kwark = {}
forms = [self.nevra_forms[command] for command in self.opts.command
if command in list(self.nevra_forms.keys())]
@@ -423,6 +439,11 @@ def run(self):
kwark["forms"] = forms
pkgs = []
query_results = q.filter(empty=True)
+
+ if remote_packages:
+ query_results = query_results.union(
+ self.base.sack.query().filterm(pkg=remote_packages))
+
for key in self.opts.key:
query_results = query_results.union(
dnf.subject.Subject(key, ignore_case=True).get_best_query(

View File

@ -0,0 +1,26 @@
From 8df2ca3485b0c758d2030b096ecc6acac0d2d462 Mon Sep 17 00:00:00 2001
From: nsella <nsella@redhat.com>
Date: Thu, 9 Jan 2020 11:13:48 +0100
Subject: [PATCH] Add doc entry: include url (RhBug 1786072)
---
doc/cli_vs_yum.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/doc/cli_vs_yum.rst b/doc/cli_vs_yum.rst
index 5c03b598f3..199ef2fefb 100644
--- a/doc/cli_vs_yum.rst
+++ b/doc/cli_vs_yum.rst
@@ -93,6 +93,12 @@ following will work::
``include`` directive name of [main] and Repo configuration is a more logical and better named counterpart of ``exclude`` in DNF.
+=======================================
+The ``include`` option has been removed
+=======================================
+
+Inclusion of other configuration files in the main configuration file is no longer supported.
+
====================================================
``dnf provides /bin/<file>`` is not fully supported
====================================================

View File

@ -0,0 +1,138 @@
From 9d19491f52cad798ce995f3f8d1c13e2dc54cb0c Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Sun, 12 Jan 2020 15:52:16 +0100
Subject: [PATCH 1/2] Split loggers setup so that file loggers could be set
separately
---
dnf/logging.py | 46 +++++++++++++++++++++++++++++++---------------
1 file changed, 31 insertions(+), 15 deletions(-)
diff --git a/dnf/logging.py b/dnf/logging.py
index df355efa57..bd660470a3 100644
--- a/dnf/logging.py
+++ b/dnf/logging.py
@@ -132,12 +132,14 @@ def _paint_mark(logger):
class Logging(object):
def __init__(self):
self.stdout_handler = self.stderr_handler = None
-
- @only_once
- def _presetup(self):
logging.addLevelName(DDEBUG, "DDEBUG")
logging.addLevelName(SUBDEBUG, "SUBDEBUG")
logging.addLevelName(TRACE, "TRACE")
+ logging.captureWarnings(True)
+ logging.raiseExceptions = False
+
+ @only_once
+ def _presetup(self):
logger_dnf = logging.getLogger("dnf")
logger_dnf.setLevel(TRACE)
@@ -155,24 +157,19 @@ def _presetup(self):
self.stderr_handler = stderr
@only_once
- def _setup(self, verbose_level, error_level, logdir, log_size, log_rotate):
- self._presetup()
+ def _setup_file_loggers(self, verbose_level, logdir, log_size, log_rotate):
logger_dnf = logging.getLogger("dnf")
+ logger_dnf.setLevel(TRACE)
# setup file logger
logfile = os.path.join(logdir, dnf.const.LOG)
handler = _create_filehandler(logfile, log_size, log_rotate)
logger_dnf.addHandler(handler)
- # temporarily turn off stdout/stderr handlers:
- self.stdout_handler.setLevel(SUPERCRITICAL)
- self.stderr_handler.setLevel(SUPERCRITICAL)
# put the marker in the file now:
_paint_mark(logger_dnf)
# setup Python warnings
- logging.captureWarnings(True)
logger_warnings = logging.getLogger("py.warnings")
- logger_warnings.addHandler(self.stderr_handler)
logger_warnings.addHandler(handler)
lr_logfile = os.path.join(logdir, dnf.const.LOG_LIBREPO)
@@ -184,22 +181,41 @@ def _setup(self, verbose_level, error_level, logdir, log_size, log_rotate):
logger_rpm.setLevel(SUBDEBUG)
logfile = os.path.join(logdir, dnf.const.LOG_RPM)
handler = _create_filehandler(logfile, log_size, log_rotate)
- logger_rpm.addHandler(self.stdout_handler)
- logger_rpm.addHandler(self.stderr_handler)
logger_rpm.addHandler(handler)
_paint_mark(logger_rpm)
+
+ @only_once
+ def _setup(self, verbose_level, error_level, logdir, log_size, log_rotate):
+ self._presetup()
+
+ # temporarily turn off stdout/stderr handlers:
+ self.stdout_handler.setLevel(SUPERCRITICAL)
+ self.stderr_handler.setLevel(SUPERCRITICAL)
+
+ self._setup_file_loggers(verbose_level, logdir, log_size, log_rotate)
+
+ logger_warnings = logging.getLogger("py.warnings")
+ logger_warnings.addHandler(self.stderr_handler)
+
+ # setup RPM callbacks logger
+ logger_rpm = logging.getLogger("dnf.rpm")
+ logger_rpm.addHandler(self.stdout_handler)
+ logger_rpm.addHandler(self.stderr_handler)
+
# bring std handlers to the preferred level
self.stdout_handler.setLevel(verbose_level)
self.stderr_handler.setLevel(error_level)
- logging.raiseExceptions = False
- def _setup_from_dnf_conf(self, conf):
+ def _setup_from_dnf_conf(self, conf, file_loggers_only=False):
verbose_level_r = _cfg_verbose_val2level(conf.debuglevel)
error_level_r = _cfg_err_val2level(conf.errorlevel)
logdir = conf.logdir
log_size = conf.log_size
log_rotate = conf.log_rotate
- return self._setup(verbose_level_r, error_level_r, logdir, log_size, log_rotate)
+ if file_loggers_only:
+ return self._setup_file_loggers(verbose_level_r, logdir, log_size, log_rotate)
+ else:
+ return self._setup(verbose_level_r, error_level_r, logdir, log_size, log_rotate)
class Timer(object):
From e43eaba4148446523eaf3e8ff1549c7576d00f1c Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Sun, 12 Jan 2020 15:53:09 +0100
Subject: [PATCH 2/2] New API function base.setup_loggers() (RhBug:1788212)
Gives API users ability to setup DNF loggers.
https://bugzilla.redhat.com/show_bug.cgi?id=1788212
---
dnf/base.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/dnf/base.py b/dnf/base.py
index b2c17bba30..56a9dfb478 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -2536,6 +2536,14 @@ def _raise_package_not_installed_error(self, pkg_spec, forms, reponame):
msg = _('All matches were filtered out by exclude filtering for argument')
raise dnf.exceptions.PackagesNotInstalledError(msg, pkg_spec)
+ def setup_loggers(self):
+ # :api
+ """
+ Setup DNF file loggers based on given configuration file. The loggers are set the same
+ way as if DNF was run from CLI.
+ """
+ self._logging._setup_from_dnf_conf(self.conf, file_loggers_only=True)
+
def _msg_installed(pkg):
name = ucd(pkg)

View File

@ -1,11 +1,11 @@
# default dependencies
%global hawkey_version 0.35.1-9
%global hawkey_version 0.39.1
%global libcomps_version 0.1.8
%global libmodulemd_version 1.4.0
%global rpm_version 4.14.0
%global rpm_version 4.14.2-35
# conflicts
%global conflicts_dnf_plugins_core_version 4.0.6
%global conflicts_dnf_plugins_core_version 4.0.12
%global conflicts_dnf_plugins_extras_version 4.0.4
%global conflicts_dnfdaemon_version 0.3.19
@ -47,6 +47,8 @@
%global yum_compat_level full
%global yum_subpackage_name yum
%if 0%{?fedora}
# Avoid file conflict with yum < 4 in all Fedoras
# It can be resolved by pretrans scriptlet but they are not recommended in Fedora
%global yum_compat_level minimal
%if 0%{?fedora} < 31
# Avoid name conflict with yum < 4
@ -79,25 +81,30 @@
It supports RPMs, modules and comps groups & environments.
Name: dnf
Version: 4.2.7
Release: 7%{?dist}
Version: 4.2.17
Release: 6%{?dist}
Summary: %{pkg_summary}
# For a breakdown of the licensing, see PACKAGE-LICENSING
License: GPLv2+ and GPLv2 and GPL
URL: https://github.com/rpm-software-management/dnf
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
# Temporary patch to not fail on modular RPMs without modular metadata
# until the infrastructure is ready
Patch2: 0002-Update-localizations-from-zanata-RhBug1689982.patch
Patch3: 0003-Accept-multiple-specs-in-repoquery-options-RhBug16678981656801.patch
Patch4: 0004-Prevent-switching-modules-in-all-cases-RhBug1706215.patch
Patch5: 0005-Change-synchronization-of-rpm-transaction-to-swdb-RhBug1737328.patch
Patch6: 0006-Print-rpm-error-messages-during-transaction-RhBug1677199.patch
Patch7: 0007-Report-missing-default-profile-as-an-error-RhBug16695271724564.patch
Patch8: 0008-doc-Describe-a-behavior-when-plugin-is-removed-RhBug1700741.patch
Patch9: 0009-Prevent-printing-empty-Error-Summary-RhBug-1690414.patch
Patch10: 0010-Fix---setopt-and-repo-with-dots.patch
Patch11: 0011-Keep-installed-packages-in-upgrade-job-RhBug172825216442411741381.patch
Patch1: 0001-Do-a-substitution-of-variables-in-repo_id-RhBug1748841.patch
Patch2: 0002-Fix-and-document-order-of-config-files-in-aliasesd-RhBug1680489.patch
Patch3: 0003-doc-Remove-note-about-whitelist.patch
Patch4: 0004-Fix-detection-of-the-latest-module-RhBug1781769.patch
Patch5: 0005-Unify-downgrade-exit-codes-with-upgrade-RhBug1759847.patch
Patch6: 0006-Restore-functionality-of-remove-oldinstallonly.patch
Patch7: 0007-Shell-restriction-with-local-packages.patch
Patch8: 0008-Improve-help-for-dnf-module-command-RhBug1758447.patch
Patch9: 0009-Fix-alias-processing-with-backslash-escaping-RhBug1680482.patch
Patch10: 0010-Honor-priority-with-check-update-RhBug1769466.patch
Patch11: 0011-Better-descriptions-for-infinite-aliases-recursion-RhBug1680488.patch
Patch12: 0012-doc-Explain-the-backslash-notation-also-near-the-example-RhBug1680482.patch
Patch13: 0013-Update-translations-from-zanata-RhBug-1754959.patch
Patch14: 0014-Sort-packages-in-transaction-output-by-nevra-RhBug-1773436.patch
Patch15: 0015-Add-support-of-commandline-packages-by-repoquery-RhBug-1784148.patch
Patch16: 0016-Documentation-changes-RhBug-1786072.patch
Patch17: 0017-New-API-function-for-setting-loggers-RhBug-1788212.patch
BuildArch: noarch
BuildRequires: cmake
@ -123,7 +130,6 @@ Recommends: (python2-dbus if NetworkManager)
%endif
Recommends: (%{_bindir}/sqlite3 if bash-completion)
%endif
%{?systemd_requires}
Provides: dnf-command(alias)
Provides: dnf-command(autoremove)
Provides: dnf-command(check-update)
@ -170,7 +176,7 @@ Summary: %{pkg_summary}
%if 0%{?fedora}
%if 0%{?fedora} >= 31
Provides: %{name}-yum = %{version}-%{release}
Obsoletes: %{name}-yum < %{version}-%{release}
Obsoletes: %{name}-yum < 5
%else
Conflicts: yum < 3.4.3-505
%endif
@ -338,6 +344,13 @@ mv %{buildroot}%{_bindir}/dnf-automatic-2 %{buildroot}%{_bindir}/dnf-automatic
%endif
rm -vf %{buildroot}%{_bindir}/dnf-automatic-*
# Strict conf distribution
%if 0%{?rhel}
mv -f %{buildroot}%{confdir}/%{name}-strict.conf %{buildroot}%{confdir}/%{name}.conf
%else
rm -vf %{buildroot}%{confdir}/%{name}-strict.conf
%endif
# YUM compat layer
ln -sr %{buildroot}%{confdir}/%{name}.conf %{buildroot}%{_sysconfdir}/yum.conf
%if %{with python3}
@ -515,6 +528,89 @@ ln -sr %{buildroot}%{confdir}/vars %{buildroot}%{_sysconfdir}/yum/vars
%endif
%changelog
* Tue Feb 18 2020 Ales Matej <amatej@redhat.com> - 4.2.17-6
- Sort packages in transaction output by nevra (RhBug:1773436)
- Add support of commandline packages by repoquery (RhBug:1784148)
- [doc] Document that the include option was removed (RhBug:1786072)
- New API function for setting loggers (RhBug:1788212)
* Fri Jan 31 2020 Marek Blaha <mblaha@redhat.com> - 4.2.17-5
- [translations] Update translations from zanata (RhBug:1754959)
* Mon Jan 13 2020 Ales Matej <amatej@redhat.com> - 4.2.17-4
- Fix alias processing with '\' escaping (RhBug:1680482)
- [doc] Explain the backslash notation also near the example (RhBug:1680482)
- Better descriptions for infinite aliases recursion (RhBug:1680488)
- Improve help for 'dnf module' command (RhBug:1758447)
- Unify downgrade exit codes with upgrade (RhBug:1759847)
- Honor priority with check-update (RhBug:1769466)
- Add shell restriction with local packages (RhBug:1773483)
- Restore functionality of remove --oldinstallonly (RhBug:1774670)
* Thu Dec 12 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 4.2.17-3
- Do a substitution of variables in repo_id (RhBug:1748841)
- Respect order of config files in aliases.d (RhBug:1680489)
- [doc] Remove note about user-agent whitelist (RhBug:1777255)
- Fix detection of the latest module (RhBug:1781769)
* Mon Nov 25 2019 Ales Matej <amatej@redhat.com> - 4.2.17-2
- Update to 4.2.17
- Enable versionlock for check-update command (RhBug:1750620)
- Add error message when no active modules matched (RhBug:1696204)
- Log mirror failures as warning when repo load fails (RhBug:1713627)
- dnf-automatic: Change all systemd timers to a fixed time of day (RhBug:1754609)
- DNF can use config from the remote location (RhBug:1721091)
- [doc] update reference to plugin documentation (RhBug:1706386)
- [yum compatibility] Report all packages in repoinfo
- [doc] Add definition of active/inactive module stream
- repoquery: Add a switch to disable modular excludes
- Report more informative messages when no match for argument (RhBug:1709563)
- [doc] Add description of excludes in dnf
- Report more descriptive message when removed package is excluded
- Add module repoquery command
- Fix assumptions about ARMv8 and the way the rpm features work (RhBug:1691430)
- Add Requires information into module info commands
- Enhance inheritance of transaction reasons (RhBug:1672618,1769788)
* Wed Nov 13 2019 Ales Matej <amatej@redhat.com> - 4.2.16-1
- Update to 4.2.16
- Fix downloading local packages into destdir (RhBug:1727137)
- Report skipped packages with identical nevra only once (RhBug:1643109)
- Restore functionality of dnf remove --duplicates (RhBug:1674296)
- Improve API documentation
- Document NEVRA parsing in the man page
- Do not wrap output when no terminal (RhBug:1577889)
- Allow to ship alternative dnf.conf (RhBug:1752249)
- Don't check if repo is expired if it doesn't have loaded metadata (RhBug:1745170)
- Remove duplicate entries from "dnf search" output (RhBug:1742926)
- Set default value of repo name attribute to repo id (RhBug:1669711)
- Allow searching in disabled modules using "dnf module provides" (RhBug:1629667)
- Group install takes obsoletes into account (RhBug:1761137)
- Improve handling of vars
- Do not load metadata for repolist commands (RhBug:1697472,1713055,1728894)
- Fix messages for starting and failing scriptlets (RhBug:1724779)
- Don't show older install-only pkgs updates in updateinfo (RhBug:1649383,1728004)
- Add --ids option to the group command (RhBug:1706382)
- Add --with_cve and --with_bz options to the updateinfo command (RhBug:1750528)
* Tue Oct 22 2019 Ales Matej <amatej@redhat.com> - 4.2.11-1
- Update to 4.2.11
- Improve modularity documentation (RhBug:1730162,1730162,1730807,1734081)
- Fix detection whether system is running on battery (used by metadata caching timer) (RhBug:1498680)
- New repoquery queryformat: %{reason}
- Print rpm errors during test transaction (RhBug:1730348)
- Fix incorrectly marked profile and stream after failed rpm transaction check (RhBug:1719679)
- Show transaction errors inside dnf shell (RhBug:1743644)
- dnf-automatic now respects versionlock excludes (RhBug:1746562)
- [doc] Add user_agent and countme options
- [history] Don't store failed transactions as succeeded
- [history] Do not require root for informative commands
- [dnssec] Fix UnicodeWarning when using new rpm (RhBug:1699650)
- Apply excludes before modular excludes (RhBug:1709453)
- Improve help for command line arguments (RhBug:1659328)
- Add new modular API method ModuleBase.get_modules
- Mark features used by ansible, anaconda and subscription-manager as an API
* Mon Oct 21 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 4.2.7-7
- Prevent reinstalling modified packages with same NEVRA (RhBug:1728252,1644241,1760825)