#!/usr/bin/env bash # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2026 Bryan Joshua Pedini # Executable proof for discovery/pacman.md. Run inside archlinux:latest: # docker run --rm -i -v "$PWD/discovery/pacman:/d:ro" archlinux:latest bash /d/checks.sh # Needs network (real repos + pacman-contrib for the pactree comparison). export LC_ALL=C fails=0 ok() { printf 'PASS %s\n' "$*"; } bad() { printf 'FAIL %s\n' "$*"; fails=$((fails+1)); } eq() { # eq if [ "$2" = "$3" ]; then ok "$1"; else bad "$1"; printf ' expected: %q\n actual: %q\n' "$2" "$3"; fi } d=$(dirname "$(readlink -f "$0")") bash "$d/fixture.sh" 2>&1 | grep -v 'database file for' . "$d/lib.sh" echo "### 1/2 refresh + upgradable" pm_refresh >/dev/null 2>&1; eq "pm_refresh exit" 0 $? pm_upgradable | grep '^su-dummy' > /tmp/up.tsv eq "upgradable su-dummy rows" $'su-dummy-a\t1.0-1\t2.0-1\tsu-dummy\t0\nsu-dummy-b\t1.0-1\t2.0-1\tsu-dummy\t0\nsu-dummy-c\t1.0-1\t2.0-1\tsu-dummy\t0' "$(cat /tmp/up.tsv)" pm_upgradable | head -3 | sed 's/^/ /' echo 'IgnorePkg = su-dummy-c' > /etc/pacman.d/ignorepkg eq "ignored flag" $'su-dummy-c\t1.0-1\t2.0-1\tsu-dummy\t1' "$(pm_upgradable | grep '^su-dummy-c')" eq "pacman-conf IgnorePkg" su-dummy-c "$(pm_ignored_patterns)" : > /etc/pacman.d/ignorepkg echo "### 3 descriptions" eq "local desc" $'bash\tThe GNU Bourne Again shell' "$(pm_desc_local bash)" eq "cand desc" $'su-dummy-a\tSkeptical-updater dummy package A' "$(pm_desc_cand su-dummy/su-dummy-a)" eq "desc wrapped input is unwrapped" $'bash\tThe GNU Bourne Again shell' "$(COLUMNS=20 pm_desc_local bash)" eq "desc via raw COLUMNS=20 wraps" yes "$( [ "$(COLUMNS=20 pacman -Qi bash | grep -c '^ \{10,\}')" -gt 0 ] && echo yes || echo no )" echo "### 4 reverse deps" eq "required-by su-dummy-b" su-dummy-a "$(pm_required_by su-dummy-b)" eq "required-by su-dummy-a (None => empty)" "" "$(pm_required_by su-dummy-a)" eq "required-by readline (soname dep)" "bash" "$(pm_required_by readline | grep -x bash)" eq "optional-for bash" "ncurses pcre2 tzdata" "$(pm_optional_for bash | tr '\n' ' ' | sed 's/ $//')" echo "### 5 closure vs pactree" pacman -S --noconfirm --needed pacman-contrib fakeroot >/dev/null 2>&1 # fakeroot only for checkupdates for p in bash pacman su-dummy-a; do mine=$(pm_closure "$p" | tr '\n' ' ') ref=$(pactree -l -u "$p" | xargs -r pacman -Qq -- 2>/dev/null | sort -u | grep -vx "$p" | tr '\n' ' ') eq "closure($p) == pactree|resolve" "$ref" "$mine" printf ' %s -> %s packages\n' "$p" "$(echo $mine | wc -w)" done eq "closure(sh) resolves provider" "$(pm_closure bash)" "$(pm_closure sh)" eq "reverse closure(su-dummy-b)" su-dummy-a "$(pm_closure -r su-dummy-b)" for p in glibc bash; do mine=$(pm_closure -r "$p" | tr '\n' ' ') ref=$(pactree -r -l -u "$p" | xargs -r pacman -Qq -- 2>/dev/null | sort -u | grep -vx "$p" | tr '\n' ' ') eq "reverse closure($p) == pactree -r" "$ref" "$mine" done echo "### 6 plan / ignore / apply" eq "plan all" $'su-dummy/su-dummy-b 2.0-1\nsu-dummy/su-dummy-a 2.0-1\nsu-dummy/su-dummy-c 2.0-1' "$(pm_plan | grep su-dummy)" eq "plan skip a,c" $'su-dummy/su-dummy-b 2.0-1' "$(pm_plan su-dummy-a su-dummy-c | grep su-dummy)" pm_apply su-dummy-a,su-dummy-c >/dev/null 2>&1; eq "apply (comma list passed as one arg) exit" 0 $? eq "after partial apply" $'su-dummy-a 1.0-1\nsu-dummy-b 2.0-1\nsu-dummy-c 1.0-1' "$(pacman -Q su-dummy-a su-dummy-b su-dummy-c)" pm_apply su-dummy-a >/dev/null 2>&1; pm_apply >/dev/null 2>&1 eq "after full apply" $'su-dummy-a 2.0-1\nsu-dummy-b 2.0-1\nsu-dummy-c 2.0-1' "$(pacman -Q su-dummy-a su-dummy-b su-dummy-c)" echo "### 7 nothing to do / exit codes" pm_apply >/dev/null 2>&1 # real repos: upgrade everything so nothing is left pacman -Qu >/dev/null; eq "pacman -Qu exit when fully upgraded" 1 $? out=$(pacman -Su --noconfirm 2>&1); rc=$? eq "pacman -Su nothing to do: exit" 0 "$rc" eq "pacman -Su nothing to do: message" $':: Starting full system upgrade...\n there is nothing to do' "$out" checkupdates >/dev/null 2>&1; eq "checkupdates exit when nothing to do" 2 $? echo "### 8 purge" pm_purge su-dummy-b >/dev/null 2>&1; eq "purge b (needed by a) exit" 1 $? pm_purge su-dummy-a >/dev/null 2>&1; eq "purge a exit" 0 $? pacman -Q su-dummy-b >/dev/null 2>&1; eq "b removed with a (was --asdeps)" 1 $? echo [ "$fails" -eq 0 ] && echo "ALL CHECKS PASSED" || echo "$fails CHECK(S) FAILED" exit "$fails"