LibrePortal/scripts/dev/lp-uninstall-report-test
librelad 9d8b92367b uninstall: read the storage registry before deleting it
The report added last commit never fired. It reads
/usr/local/lib/libreportal/storage.roots to list which locations still hold app
data — and that directory is removed earlier in the same function, so it found
an empty registry and printed nothing.

Which is precisely the silence it was written to prevent, and worse than not
having it: indistinguishable from "there was nothing left". Caught on a clean
teardown that left an app on each of two test disks and said so about neither.

Snapshot the registry before the removal and report from that.

scripts/dev/lp-uninstall-report-test runs the real capture and report fragments
from init.sh with the deletion between them, so what it guards is the ORDER
rather than the wording. Verified by moving the capture back after the delete.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 12:43:04 +01:00

74 lines
3.3 KiB
Bash
Executable File

#!/bin/bash
# Does the teardown still say what it left behind, after deleting the thing it
# reads that from?
#
# scripts/dev/lp-uninstall-report-test
#
# A full uninstall removes the primary containers root and everything in it, but
# app data on an ADDITIONAL storage location survives. Leaving it is right —
# deleting someone's data off a separate disk unasked is worse — but saying
# nothing about it is not, especially as those directories end up owned by a uid
# that stops mapping to a user once the container account is gone.
#
# The report reads the storage registry, which lives INSIDE the helpers
# directory the same function deletes. Written after that deletion it found an
# empty registry and printed nothing: the exact silence it exists to prevent,
# and indistinguishable from "there was nothing left". So what this guards is
# not the wording but the ORDER — the capture has to happen before the delete.
#
# Runs the real fragments from init.sh with the deletion between them.
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
BASE="$(mktemp -d "${TMPDIR:-/tmp}/lp-unreport-XXXXXX")"
trap 'rm -rf "$BASE"' EXIT
fail=0
chk(){ if [[ "$2" == "$3" ]]; then echo " ok $1"; else echo " FAIL $1: got '$2' want '$3'"; fail=1; fi; }
CAPTURE=$(awk '/^\t# The storage registry lives inside the helpers directory/,/^\tfi$/' "$REPO/init.sh")
REPORT=$(awk '/^\t# App data on an ADDITIONAL storage location is not removed/,/^\tfi$/' "$REPO/init.sh")
[[ -n "$CAPTURE" ]] || { echo " FAIL could not extract the capture block from init.sh"; exit 1; }
[[ -n "$REPORT" ]] || { echo " FAIL could not extract the report block from init.sh"; exit 1; }
# A registry where the helpers live, and data on one of the two locations.
mkdir -p "$BASE/lib" "$BASE/loc1/appA" "$BASE/loc1/appB" "$BASE/loc2" "$BASE/gone"
printf '1\t%s\t1\tuuid\n2\t%s\t2\tuuid\n3\t%s\t3\tuuid\n' \
"$BASE/loc1" "$BASE/loc2" "$BASE/nonexistent" > "$BASE/lib/storage.roots"
run() {
local tmp; tmp=$(mktemp)
{
echo 'isNotice(){ echo "NOTICE: $*"; }'
# The real paths are absolute; point them at the fixture.
printf '%s\n' "$CAPTURE" | sed "s#/usr/local/lib/libreportal#$BASE/lib#g"
# The deletion that sits between them in the real function.
echo "rm -rf \"$BASE/lib\""
printf '%s\n' "$REPORT"
} > "$tmp"
bash "$tmp" 2>&1
rm -f "$tmp"
}
out=$(run)
echo "--- it reports what survived, after the registry is gone ---"
chk "registry really was deleted" "$([[ -e "$BASE/lib" ]] && echo yes || echo no)" "no"
chk "says something" "$(grep -c 'App data left' <<< "$out")" "1"
chk "names the location" "$(grep -c "$BASE/loc1" <<< "$out")" "1"
chk "counts its apps" "$(grep -c '2 app directories' <<< "$out")" "1"
echo "--- and stays quiet about locations with nothing on them ---"
chk "empty location omitted" "$(grep -c "$BASE/loc2" <<< "$out")" "0"
chk "missing path omitted" "$(grep -c 'nonexistent' <<< "$out")" "0"
echo "--- nothing left anywhere: no report at all ---"
rm -rf "$BASE/loc1/appA" "$BASE/loc1/appB"
mkdir -p "$BASE/lib"
printf '1\t%s\t1\tuuid\n' "$BASE/loc1" > "$BASE/lib/storage.roots"
out=$(run)
chk "silent when there is nothing to say" "$(grep -c 'App data left' <<< "$out")" "0"
echo ""
if (( fail )); then echo "FAILED"; exit 1; fi
echo "All uninstall-report checks passed."