From da40ed270dc84016051af69cb597e759a78f6c58 Mon Sep 17 00:00:00 2001 From: Omarchybot Date: Fri, 28 Aug 2026 05:45:47 -0700 Subject: [PATCH] Diagnose the retry that follows a deleted package Every attempt after the first fails on the open rather than on a checksum: pacstrap runs with --noconfirm, so pacman answers yes to "delete it?" and unlinks the package through the bind mount that makes the ISO's offline mirror the target's package cache. The failure screen then carried no diagnosis at all, because the only line it matched -- "is corrupted" under the target cache -- was written by the attempt that already scrolled away. A retry is the state most people are in by the time they read the screen, and it was the one case with nothing on it. pacman names the repository it read from in that error, not the cache it writes to, so the match keys on the mirror path rather than the target cache path. Where a log holds both attempts the checksum failure still wins: it is the one that names the cause, and the open failures after it are its wake. The verdict sends the reader to reboot instead of offering a remedy for the medium. Nothing can be weighed once the bytes are gone, and the deletion landed in the live session's RAM overlay rather than on the stick, so a reboot brings the ISO's copy back and the first error after it is the one that says what actually failed. --- .../local/bin/omarchy-install-diagnose-media | 36 +++++++++++ test/unit/install-media-diagnosis-test.sh | 59 +++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/configs/airootfs/usr/local/bin/omarchy-install-diagnose-media b/configs/airootfs/usr/local/bin/omarchy-install-diagnose-media index 9ce5dfd..9b33701 100755 --- a/configs/airootfs/usr/local/bin/omarchy-install-diagnose-media +++ b/configs/airootfs/usr/local/bin/omarchy-install-diagnose-media @@ -47,6 +47,21 @@ corrupt_package() { printf '%s' "$package" } +# A retry in the same boot never gets as far as a checksum. The first failure +# unlinked the package through the bind mount, so pacman now fails opening it, +# and it names the mirror it read from rather than the cache it writes to. +deleted_package() { + local log match package="" + + for log in "$@"; do + [[ -f $log ]] || continue + match=$(sed -n "s|.*Could not open file ${OFFLINE_MIRROR}/\([^ ]*\).*|\1|p" "$log" | tail -n 1) + [[ -n $match ]] && package="$match" + done + + printf '%s' "$package" +} + expected_checksum() { local package="$1" reader @@ -77,7 +92,14 @@ actual_checksum() { printf '%s' "${sum%% *}" } +# The checksum failure is read first wherever both are in the log: it is the +# attempt that names the cause, and the open failures after it are its wake. package=$(corrupt_package "$@") +deleted="" +if [[ -z $package ]]; then + package=$(deleted_package "$@") + deleted=1 +fi if [[ -z $package ]]; then exit 1 fi @@ -87,6 +109,20 @@ fi # filename has no business containing before printing it. display_package="${package//[^A-Za-z0-9._+:@%-]/}" +# Nothing can be weighed here: the bytes that failed are gone, and the copy in +# the mirror went with them. Say which attempt this is, because the screen +# otherwise repeats the same unreadable error for every retry and the one that +# explains it scrolled away with the first. +if [[ -n $deleted ]]; then + echo "An earlier attempt deleted this package" + echo "pacman rejected it off this ISO and unlinked it from the mirror:" + echo "$display_package" + echo + echo "Reboot before retrying: the deletion is in RAM, so the ISO's copy returns" + echo "The first error after that reboot is the one that names the fault" + exit 0 +fi + expected=$(expected_checksum "$package") actual=$(actual_checksum "$package") diff --git a/test/unit/install-media-diagnosis-test.sh b/test/unit/install-media-diagnosis-test.sh index cbad41d..245afa1 100755 --- a/test/unit/install-media-diagnosis-test.sh +++ b/test/unit/install-media-diagnosis-test.sh @@ -142,6 +142,65 @@ if grep -qF "no longer matches the checksum" <<<"$output"; then fi pass "a deleted package names the medium without claiming which way it failed" +# Every retry in the same boot fails on the open rather than the checksum, and +# pacman names the mirror it read from, not the cache it writes to. +write_retry_log() { + local log="$1" path="${2:-$mirror/$PACKAGE}" + + { + echo "[dashboard] :: Retrieving packages..." + echo "[dashboard] error: failed retrieving file '${path##*/}' from disk : Could not open file $path" + echo "[dashboard] error: failed to commit transaction (download library error)" + echo "[dashboard] ==> ERROR: Failed to install packages to new root" + } >"$log" +} + +write_retry_log "$work/retry.log" + +set +e +output=$(diagnose "$work/retry.log") +status=$? +set -e + +(( status == 0 )) || fail "a retry after the deletion is diagnosed" "exit status $status" +[[ $(head -n 1 <<<"$output") == "An earlier attempt deleted this package" ]] || + fail "a retry is diagnosed as a retry" "$output" +grep -qF "$PACKAGE" <<<"$output" || fail "a retry names the package" "$output" +grep -qF "Reboot before retrying" <<<"$output" || + fail "a retry says how to get the package back" "$output" +pass "a retry after the deletion says so instead of going undiagnosed" + +# A log holding both attempts must answer with the one that names the cause. +# The retries come after it and would otherwise win on recency. +printf 'a package, but damaged\n' >"$mirror/$PACKAGE" +write_mirror_db "$(printf '0%.0s' {1..64})" +{ + cat "$log" + cat "$work/retry.log" +} >"$work/both.log" + +set +e +output=$(diagnose "$work/both.log") +set -e + +[[ $(head -n 1 <<<"$output") == "The install medium is damaged" ]] || + fail "the checksum failure outranks the retries that followed it" "$output" +pass "the checksum failure outranks the retries that followed it" + +# An open failure somewhere other than the mirror was not read off this ISO. +write_retry_log "$work/retry-elsewhere.log" "/var/tmp/build/$PACKAGE" + +set +e +output=$(diagnose "$work/retry-elsewhere.log") +status=$? +set -e + +(( status == 1 )) || fail "an open failure outside the mirror is not diagnosed" "exit $status: $output" +[[ -z $output ]] || fail "an open failure outside the mirror prints nothing" "$output" +pass "an open failure outside the mirror is not blamed on the medium" + +rm "$mirror/$PACKAGE" + # A record with no %SHA256SUM% must not borrow the next record's, which would # compare a real file against another package's checksum. printf 'a package, but damaged\n' >"$mirror/$PACKAGE"