diff --git a/.dnf.metadata b/.dnf.metadata index 9d195a8..0bcc7b5 100644 --- a/.dnf.metadata +++ b/.dnf.metadata @@ -1 +1 @@ -aa91be9772da9fe26ecee20a86d651f4cec2207b SOURCES/dnf-4.2.21.tar.gz +0da07a3e6ff19430ffe39699e474439eab63ee7d SOURCES/dnf-4.2.23.tar.gz diff --git a/.gitignore b/.gitignore index 26034a4..c0cb815 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/dnf-4.2.21.tar.gz +SOURCES/dnf-4.2.23.tar.gz diff --git a/SOURCES/0001-Handle-empty-comps-group-name-RhBug1826198.patch b/SOURCES/0001-Handle-empty-comps-group-name-RhBug1826198.patch new file mode 100644 index 0000000..f6266a4 --- /dev/null +++ b/SOURCES/0001-Handle-empty-comps-group-name-RhBug1826198.patch @@ -0,0 +1,238 @@ +From 3c758a4ea670fab1f4b55fa878ebf2b2ff4b678b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= +Date: Tue, 28 Apr 2020 09:08:05 +0200 +Subject: [PATCH] Handle empty comps group name (RhBug:1826198) + +Don't crash on empty comps group/environment name. In outputs, use the +"" placeholder instead of the name. + +https://bugzilla.redhat.com/show_bug.cgi?id=1826198 +--- + dnf/cli/commands/group.py | 4 ++-- + dnf/cli/output.py | 16 ++++++++++------ + dnf/comps.py | 11 ++++++++++- + dnf/db/group.py | 12 ++++++++---- + tests/repos/main_comps.xml | 7 +++++++ + tests/support.py | 2 +- + tests/test_comps.py | 6 +++--- + tests/test_groups.py | 9 +++++++++ + 8 files changed, 50 insertions(+), 17 deletions(-) + +diff --git a/dnf/cli/commands/group.py b/dnf/cli/commands/group.py +index f535a50980..4ffd3b89c8 100644 +--- a/dnf/cli/commands/group.py ++++ b/dnf/cli/commands/group.py +@@ -177,7 +177,7 @@ def _list(self, userlist): + def _out_grp(sect, group): + if not done: + print(sect) +- msg = ' %s' % group.ui_name ++ msg = ' %s' % (group.ui_name if group.ui_name is not None else _("")) + if print_ids: + msg += ' (%s)' % group.id + if group.lang_only: +@@ -188,7 +188,7 @@ def _out_env(sect, envs): + if envs: + print(sect) + for e in envs: +- msg = ' %s' % e.ui_name ++ msg = ' %s' % (e.ui_name if e.ui_name is not None else _("")) + if print_ids: + msg += ' (%s)' % e.id + print(msg) +diff --git a/dnf/cli/output.py b/dnf/cli/output.py +index 67eab80b19..2585a5c773 100644 +--- a/dnf/cli/output.py ++++ b/dnf/cli/output.py +@@ -1221,47 +1221,51 @@ def _add_line(lines, data, a_wid, po, obsoletes=[]): + lines.append((name, "", "", "", "", "", "")) + pkglist_lines.append((action, lines)) + if self.base._history: ++ def format_line(group): ++ name = group.getName() ++ return (name if name else _(""), "", "", "", "", "", "") ++ + install_env_group = self.base._history.env._installed + if install_env_group: + action = _("Installing Environment Groups") + lines = [] + for group in install_env_group.values(): +- lines.append((group.getName(), "", "", "", "", "", "")) ++ lines.append(format_line(group)) + pkglist_lines.append((action, lines)) + upgrade_env_group = self.base._history.env._upgraded + if upgrade_env_group: + action = _("Upgrading Environment Groups") + lines = [] + for group in upgrade_env_group.values(): +- lines.append((group.getName(), "", "", "", "", "", "")) ++ lines.append(format_line(group)) + pkglist_lines.append((action, lines)) + remove_env_group = self.base._history.env._removed + if remove_env_group: + action = _("Removing Environment Groups") + lines = [] + for group in remove_env_group.values(): +- lines.append((group.getName(), "", "", "", "", "", "")) ++ lines.append(format_line(group)) + pkglist_lines.append((action, lines)) + install_group = self.base._history.group._installed + if install_group: + action = _("Installing Groups") + lines = [] + for group in install_group.values(): +- lines.append((group.getName(), "", "", "", "", "", "")) ++ lines.append(format_line(group)) + pkglist_lines.append((action, lines)) + upgrade_group = self.base._history.group._upgraded + if upgrade_group: + action = _("Upgrading Groups") + lines = [] + for group in upgrade_group.values(): +- lines.append((group.getName(), "", "", "", "", "", "")) ++ lines.append(format_line(group)) + pkglist_lines.append((action, lines)) + remove_group = self.base._history.group._removed + if remove_group: + action = _("Removing Groups") + lines = [] + for group in remove_group.values(): +- lines.append((group.getName(), "", "", "", "", "", "")) ++ lines.append(format_line(group)) + pkglist_lines.append((action, lines)) + # show skipped conflicting packages + if not self.conf.best and self.base._goal.actions & forward_actions: +diff --git a/dnf/comps.py b/dnf/comps.py +index 316d647087..4ca15b1e07 100644 +--- a/dnf/comps.py ++++ b/dnf/comps.py +@@ -75,7 +75,16 @@ def _by_pattern(pattern, case_sensitive, sqn): + else: + match = re.compile(fnmatch.translate(pattern), flags=re.I).match + +- return {g for g in sqn if match(g.name) or match(g.id) or match(g.ui_name)} ++ ret = set() ++ for g in sqn: ++ if match(g.id): ++ ret.add(g) ++ elif g.name is not None and match(g.name): ++ ret.add(g) ++ elif g.ui_name is not None and match(g.ui_name): ++ ret.add(g) ++ ++ return ret + + + def _fn_display_order(group): +diff --git a/dnf/db/group.py b/dnf/db/group.py +index e3a087760b..5d7e18d1a8 100644 +--- a/dnf/db/group.py ++++ b/dnf/db/group.py +@@ -78,8 +78,10 @@ def _get_obj_id(self, obj): + def new(self, obj_id, name, translated_name, pkg_types): + swdb_group = self.history.swdb.createCompsGroupItem() + swdb_group.setGroupId(obj_id) +- swdb_group.setName(name) +- swdb_group.setTranslatedName(translated_name) ++ if name is not None: ++ swdb_group.setName(name) ++ if translated_name is not None: ++ swdb_group.setTranslatedName(translated_name) + swdb_group.setPackageTypes(pkg_types) + return swdb_group + +@@ -136,8 +138,10 @@ def _get_obj_id(self, obj): + def new(self, obj_id, name, translated_name, pkg_types): + swdb_env = self.history.swdb.createCompsEnvironmentItem() + swdb_env.setEnvironmentId(obj_id) +- swdb_env.setName(name) +- swdb_env.setTranslatedName(translated_name) ++ if name is not None: ++ swdb_env.setName(name) ++ if translated_name is not None: ++ swdb_env.setTranslatedName(translated_name) + swdb_env.setPackageTypes(pkg_types) + return swdb_env + +diff --git a/tests/repos/main_comps.xml b/tests/repos/main_comps.xml +index 9e694d13a5..584bb25b3a 100644 +--- a/tests/repos/main_comps.xml ++++ b/tests/repos/main_comps.xml +@@ -49,6 +49,13 @@ + brokendeps + + ++ ++ missing-name-group ++ ++ ++ meaning-of-life ++ ++ + + base-system + 99 +diff --git a/tests/support.py b/tests/support.py +index e549ba5b95..a7d6a8542c 100644 +--- a/tests/support.py ++++ b/tests/support.py +@@ -94,7 +94,7 @@ def mock_open(mock=None, data=None): + MAIN_NSOLVABLES = 9 + UPDATES_NSOLVABLES = 4 + AVAILABLE_NSOLVABLES = MAIN_NSOLVABLES + UPDATES_NSOLVABLES +-TOTAL_GROUPS = 4 ++TOTAL_GROUPS = 5 + TOTAL_NSOLVABLES = SYSTEM_NSOLVABLES + AVAILABLE_NSOLVABLES + + +diff --git a/tests/test_comps.py b/tests/test_comps.py +index 30d468e3af..763218587f 100644 +--- a/tests/test_comps.py ++++ b/tests/test_comps.py +@@ -107,7 +107,7 @@ def test_group_packages(self): + def test_iteration(self): + comps = self.comps + self.assertEqual([g.name for g in comps.groups_iter()], +- ['Base', 'Solid Ground', "Pepper's", "Broken Group"]) ++ ['Base', 'Solid Ground', "Pepper's", "Broken Group", None]) + self.assertEqual([c.name for c in comps.categories_iter()], + ['Base System']) + g = dnf.util.first(comps.groups_iter()) +@@ -115,7 +115,7 @@ def test_iteration(self): + + def test_group_display_order(self): + self.assertEqual([g.name for g in self.comps.groups], +- ["Pepper's", 'Base', 'Solid Ground', 'Broken Group']) ++ ["Pepper's", 'Base', 'Solid Ground', 'Broken Group', None]) + + def test_packages(self): + comps = self.comps +@@ -127,7 +127,7 @@ def test_packages(self): + + def test_size(self): + comps = self.comps +- self.assertLength(comps, 6) ++ self.assertLength(comps, 7) + self.assertLength(comps.groups, tests.support.TOTAL_GROUPS) + self.assertLength(comps.categories, 1) + self.assertLength(comps.environments, 1) +diff --git a/tests/test_groups.py b/tests/test_groups.py +index fe388f96c0..8972da687e 100644 +--- a/tests/test_groups.py ++++ b/tests/test_groups.py +@@ -295,6 +295,15 @@ def test_group_install_broken_optional_nonstrict(self): + self.assertLength(inst, 1) + self.assertEmpty(removed) + ++ def test_group_install_missing_name(self): ++ comps_group = self.base.comps.group_by_pattern('missing-name-group') ++ ++ cnt = self.base.group_install(comps_group.id, ('mandatory', 'default', 'optional'), ++ strict=False) ++ self._swdb_commit() ++ self.base.resolve() ++ self.assertEqual(cnt, 1) ++ + + class EnvironmentInstallTest(tests.support.ResultTestCase): + """Set up a test where sugar is considered not installed.""" diff --git a/SPECS/dnf.spec b/SPECS/dnf.spec index 0e5c168..5207358 100644 --- a/SPECS/dnf.spec +++ b/SPECS/dnf.spec @@ -1,11 +1,11 @@ # default dependencies -%global hawkey_version 0.46.2 +%global hawkey_version 0.48.0 %global libcomps_version 0.1.8 %global libmodulemd_version 1.4.0 %global rpm_version 4.14.2-35 # conflicts -%global conflicts_dnf_plugins_core_version 4.0.12 +%global conflicts_dnf_plugins_core_version 4.0.16 %global conflicts_dnf_plugins_extras_version 4.0.4 %global conflicts_dnfdaemon_version 0.3.19 @@ -81,13 +81,15 @@ It supports RPMs, modules and comps groups & environments. Name: dnf -Version: 4.2.21 -Release: 1%{?dist} +Version: 4.2.23 +Release: 2%{?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 +Patch1: 0001-Handle-empty-comps-group-name-RhBug1826198.patch + BuildArch: noarch BuildRequires: cmake BuildRequires: gettext @@ -137,8 +139,8 @@ Provides: dnf-command(upgrade) Provides: dnf-command(upgrade-to) Conflicts: python2-dnf-plugins-core < %{conflicts_dnf_plugins_core_version} Conflicts: python3-dnf-plugins-core < %{conflicts_dnf_plugins_core_version} -Conflicts: python2-dnf-plugins-extras < %{conflicts_dnf_plugins_extras_version} -Conflicts: python3-dnf-plugins-extras < %{conflicts_dnf_plugins_extras_version} +Conflicts: python2-dnf-plugins-extras-common < %{conflicts_dnf_plugins_extras_version} +Conflicts: python3-dnf-plugins-extras-common < %{conflicts_dnf_plugins_extras_version} %description %{pkg_description} @@ -506,6 +508,35 @@ ln -sr %{buildroot}%{confdir}/vars %{buildroot}%{_sysconfdir}/yum/vars %endif %changelog +* Wed Jun 10 2020 Ales Matej - 4.2.23-2 +- Handle empty comps group name (RhBug:1826198) + +* Tue Jun 02 2020 Nicola Sella - 4.2.23-1 +- Update to 4.2.23 +- Fix behavior of `install-n` command +- Fix behavior of `localinstall` command +- Fix behavior of `autoremove-n` command +- Fix behavior of `remove-n` command +- Fix behavior of `repoquery-n` command +- Fix behavior of `list-updateinfo` and related aliases +- Refactor code in `repoinfo` to use opts.command correctly. +- Add myself to list of contributors +- Add updated to verbose output of updateinfo list (RhBug: 1801092) +- Fix a couple of missed grammatical errors in updateinfo docs. +- Add comment option (RhBug:1773679) +- Better wording of dnssec email parsing error. +- Print nicer DnssecErrors (RhBug:1813244) +- Add new API for handling gpg signatures (RhBug:1339617) +- Verify GPG signatures (RhBug:1793298) +- Fix a syntax typo +- Fix up Conflicts: on python-dnf-plugins-extras so it actually works +- [doc] Move yum-plugin-post-transaction-actions to dnf-plugins-core +- Remove args "--set-enabled", "--set-disabled" from DNF (RhBug:1727882) +- Search command is now alphabetical (RhBug:1811802) +- Fix downloading packages with full URL as their location +- repo: catch libdnf.error.Error in addition to RuntimeError in load() (RhBug:1788182) +- History tbl to max size when redirect to file (RhBug:1786335,1786316) + * Mon Apr 06 2020 Ales Matej - 4.2.21-1 - Update to 4.2.21 - Running with tsflags=test doesn't update log files