Fix two holes in the removal gate, found by reading the prune script

ubuntu-desktop-prune.sh has had this same guardrail all along, and parses
the simulation more carefully than the version I wrote for the converter.
Two differences were real bugs:

apt-get -s emits the architecture qualifier in multiarch situations, so a
critical removal appears as "Remv sudo:amd64". The exact match against
CRITICAL_PACKAGES compared that against "sudo" and did not match -- the
gate would have waved through the single case it exists to stop. The
suffix is now stripped, as the prune script already did.

apt also prints "Purg <pkg>" for purges, not only "Remv". Those were not
matched at all, so a purged package counted toward neither the critical
check nor the removal threshold.

Verified against simulated output: "Remv sudo:amd64" and
"Purg systemd:amd64" now both abort, and a mixed non-critical set still
passes.
This commit is contained in:
2026-08-22 22:40:55 -07:00
parent ece4ac2735
commit 4ae104c892
+10 -2
View File
@@ -823,9 +823,17 @@ simulate_and_gate() {
die "APT could not resolve the Mint stack (exit ${rc}). Nothing has been installed. Full output: ${sim_out}"
fi
# `Remv <name> [version]` is what apt-get -s prints for each removal.
# apt-get -s prints `Remv <name> [version]` for removals and `Purg <name>`
# for purges -- both take the package away, so both count. It also emits
# the architecture qualifier in multiarch situations ("Remv sudo:amd64"),
# which has to be stripped or a critical package would slip past the exact
# match below. ubuntu-desktop-prune.sh already parses it this way.
local -a removals=()
mapfile -t removals < <(awk '$1=="Remv"{print $2}' "$sim_out" | sort -u)
mapfile -t removals < <(
awk '/^(Remv|Purg)[[:space:]]+/{print $2}' "$sim_out" \
| sed -E 's/:[a-z0-9]+$//' \
| sort -u
)
local count=${#removals[@]}
# Critical packages first: no threshold makes these acceptable.