From a74cb7375b4bdfae977ca613d09c08294c312668 Mon Sep 17 00:00:00 2001 From: Brian Stinson Date: Jan 15 2020 16:54:44 +0000 Subject: build DNF dnf-4.2.17 for CentOS Stream --- diff --git a/.dnf.metadata b/.dnf.metadata index 39d5fd8..23af9e3 100644 --- a/.dnf.metadata +++ b/.dnf.metadata @@ -1 +1 @@ -5b789329d4fc3e54190e637f1f046232681c8f5f SOURCES/dnf-4.2.7.tar.gz +535f46b9a5242a315e1269a59372362013a5a6f0 SOURCES/dnf-4.2.17.tar.gz diff --git a/.gitignore b/.gitignore index 84adf03..56393f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/dnf-4.2.7.tar.gz +SOURCES/dnf-4.2.17.tar.gz diff --git a/SOURCES/0001-Do-a-substitution-of-variables-in-repo_id-RhBug1748841.patch b/SOURCES/0001-Do-a-substitution-of-variables-in-repo_id-RhBug1748841.patch new file mode 100644 index 0000000..13def6c --- /dev/null +++ b/SOURCES/0001-Do-a-substitution-of-variables-in-repo_id-RhBug1748841.patch @@ -0,0 +1,101 @@ +From 8bcd196fd95e70fd1f0be16d2c274e39a1cabe2e Mon Sep 17 00:00:00 2001 +From: Jaroslav Rohel +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 + diff --git a/SOURCES/0002-Fix-and-document-order-of-config-files-in-aliasesd-RhBug1680489.patch b/SOURCES/0002-Fix-and-document-order-of-config-files-in-aliasesd-RhBug1680489.patch new file mode 100644 index 0000000..993040f --- /dev/null +++ b/SOURCES/0002-Fix-and-document-order-of-config-files-in-aliasesd-RhBug1680489.patch @@ -0,0 +1,67 @@ +From ba3615c600532a0ce8693a626a9cbe71a458399a Mon Sep 17 00:00:00 2001 +From: Pavla Kratochvilova +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 +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 + diff --git a/SOURCES/0003-Accept-multiple-specs-in-repoquery-options-RhBug16678981656801.patch b/SOURCES/0003-Accept-multiple-specs-in-repoquery-options-RhBug16678981656801.patch deleted file mode 100644 index 3f43a04..0000000 --- a/SOURCES/0003-Accept-multiple-specs-in-repoquery-options-RhBug16678981656801.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 524950fb6c647194ad9e0d3b7b2195d671424d1c Mon Sep 17 00:00:00 2001 -From: Jaroslav Mracek -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 - diff --git a/SOURCES/0003-doc-Remove-note-about-whitelist.patch b/SOURCES/0003-doc-Remove-note-about-whitelist.patch new file mode 100644 index 0000000..2b0d987 --- /dev/null +++ b/SOURCES/0003-doc-Remove-note-about-whitelist.patch @@ -0,0 +1,32 @@ +From 3c473306e5e1b630a3030791fb1ef7ea0c0cd823 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +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 + diff --git a/SOURCES/0004-Fix-detection-of-the-latest-module-RhBug1781769.patch b/SOURCES/0004-Fix-detection-of-the-latest-module-RhBug1781769.patch new file mode 100644 index 0000000..89a9e19 --- /dev/null +++ b/SOURCES/0004-Fix-detection-of-the-latest-module-RhBug1781769.patch @@ -0,0 +1,157 @@ +From c8d79c0b9956aeeb8cd3a0422656b030d4656578 Mon Sep 17 00:00:00 2001 +From: Jaroslav Mracek +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 +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 + diff --git a/SOURCES/0004-Prevent-switching-modules-in-all-cases-RhBug1706215.patch b/SOURCES/0004-Prevent-switching-modules-in-all-cases-RhBug1706215.patch deleted file mode 100644 index 62aa533..0000000 --- a/SOURCES/0004-Prevent-switching-modules-in-all-cases-RhBug1706215.patch +++ /dev/null @@ -1,99 +0,0 @@ -From d53492bea1ed9c08710af75c54abea9a69f82757 Mon Sep 17 00:00:00 2001 -From: Jaroslav Mracek -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 ' 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 ' 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 ' command. After " -- "you reset the module, you can install the other stream.") -- raise dnf.exceptions.Error(msg) - - class UpdateSubCommand(SubCommand): - --- -libgit2 0.28.2 - diff --git a/SOURCES/0005-Change-synchronization-of-rpm-transaction-to-swdb-RhBug1737328.patch b/SOURCES/0005-Change-synchronization-of-rpm-transaction-to-swdb-RhBug1737328.patch deleted file mode 100644 index 087e8f3..0000000 --- a/SOURCES/0005-Change-synchronization-of-rpm-transaction-to-swdb-RhBug1737328.patch +++ /dev/null @@ -1,435 +0,0 @@ -From f6ffdce83004acdb2325d966ad348dfe63fb55f8 Mon Sep 17 00:00:00 2001 -From: Jaroslav Mracek -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 -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 -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 -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 -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 - diff --git a/SOURCES/0006-Print-rpm-error-messages-during-transaction-RhBug1677199.patch b/SOURCES/0006-Print-rpm-error-messages-during-transaction-RhBug1677199.patch deleted file mode 100644 index c629e19..0000000 --- a/SOURCES/0006-Print-rpm-error-messages-during-transaction-RhBug1677199.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 6a6ab3e12b4fe0f3fc402a6b99932640fabccc32 Mon Sep 17 00:00:00 2001 -From: Marek Blaha -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 -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 - diff --git a/SOURCES/0007-Report-missing-default-profile-as-an-error-RhBug16695271724564.patch b/SOURCES/0007-Report-missing-default-profile-as-an-error-RhBug16695271724564.patch deleted file mode 100644 index e6133ba..0000000 --- a/SOURCES/0007-Report-missing-default-profile-as-an-error-RhBug16695271724564.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 4662a3d342de4be584812267c5b59ed9c1f9c44e Mon Sep 17 00:00:00 2001 -From: Jaroslav Mracek -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 - diff --git a/SOURCES/0008-doc-Describe-a-behavior-when-plugin-is-removed-RhBug1700741.patch b/SOURCES/0008-doc-Describe-a-behavior-when-plugin-is-removed-RhBug1700741.patch deleted file mode 100644 index e6cbf0d..0000000 --- a/SOURCES/0008-doc-Describe-a-behavior-when-plugin-is-removed-RhBug1700741.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c638887211b3d9c0b3b1fcb6eb6b62f384d2c263 Mon Sep 17 00:00:00 2001 -From: Jaroslav Mracek -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 - diff --git a/SOURCES/0009-Prevent-printing-empty-Error-Summary-RhBug-1690414.patch b/SOURCES/0009-Prevent-printing-empty-Error-Summary-RhBug-1690414.patch deleted file mode 100644 index 5172075..0000000 --- a/SOURCES/0009-Prevent-printing-empty-Error-Summary-RhBug-1690414.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 60a8f5e3f0500720077b200ce3be46772db4f093 Mon Sep 17 00:00:00 2001 -From: Aleš Matěj -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 - diff --git a/SOURCES/0010-Fix---setopt-and-repo-with-dots.patch b/SOURCES/0010-Fix---setopt-and-repo-with-dots.patch deleted file mode 100644 index 606daf9..0000000 --- a/SOURCES/0010-Fix---setopt-and-repo-with-dots.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 5b83b191574d43299bb6d3212df06c6f20c818e7 Mon Sep 17 00:00:00 2001 -From: Jaroslav Rohel -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 - diff --git a/SOURCES/0011-Keep-installed-packages-in-upgrade-job-RhBug172825216442411741381.patch b/SOURCES/0011-Keep-installed-packages-in-upgrade-job-RhBug172825216442411741381.patch deleted file mode 100644 index 98c6420..0000000 --- a/SOURCES/0011-Keep-installed-packages-in-upgrade-job-RhBug172825216442411741381.patch +++ /dev/null @@ -1,49 +0,0 @@ -From a5c4a994f8ad2764ca8f971c39f189d5f9d7d337 Mon Sep 17 00:00:00 2001 -From: Jaroslav Mracek -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 - diff --git a/SPECS/dnf.spec b/SPECS/dnf.spec index ca812fe..14e397f 100644 --- a/SPECS/dnf.spec +++ b/SPECS/dnf.spec @@ -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 # 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,17 @@ It supports RPMs, modules and comps groups & environments. Name: dnf -Version: 4.2.7 -Release: 7%{?dist} +Version: 4.2.17 +Release: 3%{?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 BuildArch: noarch BuildRequires: cmake @@ -123,7 +117,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 +163,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 @@ -207,6 +200,9 @@ Requires: %{name}-data = %{version}-%{release} Recommends: deltarpm Recommends: python2-unbound %endif +%if 0%{?centos} +Requires: deltarpm +%endif Requires: python2-hawkey >= %{hawkey_version} Requires: python2-libdnf >= %{hawkey_version} Requires: python2-libcomps >= %{libcomps_version} @@ -244,6 +240,9 @@ Requires: %{name}-data = %{version}-%{release} %if 0%{?fedora} Recommends: deltarpm %endif +%if 0%{?centos} +Requires: deltarpm +%endif Requires: python3-hawkey >= %{hawkey_version} Requires: python3-libdnf >= %{hawkey_version} Requires: python3-libcomps >= %{libcomps_version} @@ -332,6 +331,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} @@ -509,6 +515,70 @@ ln -sr %{buildroot}%{confdir}/vars %{buildroot}%{_sysconfdir}/yum/vars %endif %changelog +* Thu Dec 12 2019 Pavla Kratochvilova - 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 - 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 - 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 - 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 - 4.2.7-7 - Prevent reinstalling modified packages with same NEVRA (RhBug:1728252,1644241,1760825)