From 799cc1c234d3679a29a870ad420d9c384a7c5acb Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Mon, 17 Jul 2023 20:37:46 +0000 Subject: [PATCH] Allow obsoletion of protected packages This is the libdnf5 companion to https://github.com/rpm-software-management/libdnf/pull/1610; if we change DNF 4, then we should also change DNF 5. There should be some mechanism for replacing even protected packages, e.g. to upgrade DNF to DNF 5. We unprotected dnf to allow this upgrade, but that solution isn't perfect; DNF 5 should be able to remove python3-dnf[1] and DNF 4 should not be able to remove DNF without installing DNF 5. @m-blaha proposed "implementing a hard-coded self-protection for each package manager", i.e. adding back the hardcoded protection of dnf and python3-dnf in DNF 4 and adding a protection of dnf5 in DNF 5. So if we want to do this, it seems we would need to allow obsoletion of protected packages to allow DNF 4 to obsolete dnf with dnf5. The running kernel is treated as a special case; obsoletes of the running kernel are still not allowed. --- libdnf5/rpm/solv/goal_private.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libdnf5/rpm/solv/goal_private.cpp b/libdnf5/rpm/solv/goal_private.cpp index 12cc29cc3..6573c9bae 100644 --- a/libdnf5/rpm/solv/goal_private.cpp +++ b/libdnf5/rpm/solv/goal_private.cpp @@ -580,12 +580,15 @@ libdnf5::GoalProblem GoalPrivate::protected_in_removals() { auto & pool = get_rpm_pool(); libdnf5::solv::SolvMap pkg_remove_list(pool->nsolvables); - for (auto index = 0; index < removes.size(); ++index) { - pkg_remove_list.add_unsafe(removes[index]); - } - for (auto index = 0; index < obsoleted.size(); ++index) { - pkg_remove_list.add_unsafe(obsoleted[index]); + for (const auto & remove : removes) { + pkg_remove_list.add_unsafe(remove); } + // 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. libdnf5::solv::SolvMap protected_pkgs(pool->nsolvables); if (protected_packages) { @@ -593,6 +596,13 @@ libdnf5::GoalProblem GoalPrivate::protected_in_removals() { } if (protected_running_kernel.id > 0) { protected_pkgs.add_unsafe(protected_running_kernel.id); + // Special case: consider the obsoletion of the running kernel as a + // removal. Obsoletion of other protected packages should be allowed. + for (const auto & obsolete : obsoleted) { + if (obsolete == protected_running_kernel.id) { + pkg_remove_list.add_unsafe(obsolete); + } + } } removal_of_protected.reset(new libdnf5::solv::SolvMap(std::move(pkg_remove_list)));