From cc1f1c5c2df44b2ac3b94af47b41cd2f23c98b20 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Fri, 2 Sep 2022 13:07:46 -0700 Subject: [PATCH] Group transactions: fail on missing non-optional packages If any default or mandatory package listed in a group does not exist, `raise dnf.exceptions.MarkingErrors`. This is a small change with a big impact and a lot of history. In the early days, dnf treated both 'package doesn't exist' and 'package exists but is not installable' as fatal errors. Shortly after Fedora and RHEL switched from yum to dnf, this was changed, because historically yum had not behaved this way, and our existing comps definitions had lots of missing packages; conditional and arch-specific comps entries also were not properly handled by all tools, so cleaning up comps was not possible. dnf was switched for a while to treat neither as fatal, which turned out to be too permissive, so eventually we gave it the same behaviour yum used to have, in #1038. These days, conditional and arch-specific comps entries work. I have just cleaned up Fedora's comps file for Rawhide, so there should be no 'missing' mandatory or default packages in any group: https://pagure.io/fedora-comps/pull-request/767 I don't know if RHEL's or CentOS's comps have been cleaned up, but if not, this presents an excellent opportunity to do it. Links to the history here: https://bugzilla.redhat.com/show_bug.cgi?id=1292892 https://bugzilla.redhat.com/show_bug.cgi?id=1427365 https://bugzilla.redhat.com/show_bug.cgi?id=1461539 https://github.com/rpm-software-management/dnf/pull/1038 Signed-off-by: Adam Williamson --- dnf/base.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/dnf/base.py b/dnf/base.py index 154eb4e37b..af61cef756 100644 --- a/dnf/base.py +++ b/dnf/base.py @@ -1690,12 +1690,13 @@ def trans_remove(query, remove_query, comps_pkg): return remove_query remove_query = self.sack.query().filterm(empty=True) - attr_fn = ((trans.install, functools.partial(trans_install, strict=True)), - (trans.install_opt, functools.partial(trans_install, strict=False)), - (trans.upgrade, trans_upgrade), - (trans.remove, trans_remove)) + attr_fn_mf = ((trans.install, functools.partial(trans_install, strict=True), True), + (trans.install_opt, functools.partial(trans_install, strict=False), False), + (trans.upgrade, trans_upgrade, True), + (trans.remove, trans_remove, True)) - for (attr, fn) in attr_fn: + missing_fatals = [] + for (attr, fn, missing_fatal) in attr_fn_mf: for comps_pkg in attr: query_args = {'name': comps_pkg.name} if (comps_pkg.basearchonly): @@ -1706,11 +1707,17 @@ def trans_remove(query, remove_query, comps_pkg): package_string = comps_pkg.name if comps_pkg.basearchonly: package_string += '.' + basearch - logger.warning(_('No match for group package "{}"').format(package_string)) + msg = _('No match for group package "{}"').format(package_string) + if missing_fatal: + missing_fatals.append(package_string) + else: + logger.warning(msg) continue remove_query = fn(q, remove_query, comps_pkg) self._goal.group_members.add(comps_pkg.name) + if missing_fatals: + raise dnf.exceptions.MarkingErrors(no_match_pkg_specs=missing_fatals) self._remove_if_unneeded(remove_query) def _build_comps_solver(self):