From 10958ca4747e37ab5ac0cfcff643eb3cf163371c Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Mon, 17 Jul 2023 15:50:41 -0400 Subject: [PATCH] Allow obsoletion of protected packages As described at the end of this comment: https://github.com/rpm-software-management/dnf/pull/1926#issue-1692834834 There should be some mechanism for replacing even protected packages, e.g. to upgrade DNF to DNF 5. Obsoleting a protected package is less likely to happen accidentally than removing it. But this change does mean that a protected package could be obsoleted, and then the obsoleter could be removed, which is perhaps not ideal. The running kernel is treated as a special case; obsoletes of the running kernel are still not allowed. IMO a better, more "declarative" way, might be to disallow any transaction that would result in a protected package no longer being provided. But I'm not sure how to do this without modifying libsolv. --- libdnf/goal/Goal.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp index 4c9904122..42c078286 100644 --- a/libdnf/goal/Goal.cpp +++ b/libdnf/goal/Goal.cpp @@ -1631,12 +1631,24 @@ Goal::Impl::protectedInRemovals() if ((!protectedPkgs || !protectedPkgs->size()) && !protect_running_kernel) return false; auto pkgRemoveList = listResults(SOLVER_TRANSACTION_ERASE, 0); + Id protected_kernel = protectedRunningKernel(); auto pkgObsoleteList = listResults(SOLVER_TRANSACTION_OBSOLETED, 0); - map_or(pkgRemoveList.getMap(), pkgObsoleteList.getMap()); + // Special case: consider the obsoletion of the running kernel as a + // removal. Obsoletion of other protected packages should be allowed. + for (size_t obsolete_index = 0; obsolete_index < pkgObsoleteList.size(); obsolete_index += 1) { + if (protected_kernel == pkgObsoleteList[obsolete_index]) { + pkgRemoveList.set(protected_kernel); + } + } + // We want to allow obsoletion of protected packages, so we do not consider + // obsoletes here, only removes. Previously, obsoletion of protected + // packages was disallowed, but there needed to be some mechanism for + // obsoleting/swapping a protected package, such as to obsolete `dnf` in + // favor of `dnf5`. Obsoleting a package is much harder to do accidentally + // than removing it. removalOfProtected.reset(new PackageSet(pkgRemoveList)); Id id = -1; - Id protected_kernel = protectedRunningKernel(); while(true) { id = removalOfProtected->next(id); if (id == -1)