Improve update and migration flow

This commit is contained in:
Ryan Hughes
2026-06-04 18:38:25 -04:00
parent c8ed1e77ae
commit 0804962619
39 changed files with 2068 additions and 84 deletions
+10
View File
@@ -94,6 +94,7 @@ from pathlib import Path
root = Path(os.environ["ROOT"])
pkgbuild = (root.parent / "omarchy-pkgs/pkgbuilds/omarchy-settings/PKGBUILD").read_text()
omarchy_pkgbuild = (root.parent / "omarchy-pkgs/pkgbuilds/omarchy/PKGBUILD").read_text()
errors = []
package_defaults = [
("default/uwsm/env.d/10-omarchy", "/usr/share/uwsm/env.d/10-omarchy", "uwsm/env"),
@@ -105,6 +106,8 @@ package_defaults = [
("default/systemd/user/bt-agent.service", "/usr/lib/systemd/user/bt-agent.service", "systemd/user/bt-agent.service"),
("default/systemd/user/omarchy-sleep-lock.service", "/usr/lib/systemd/user/omarchy-sleep-lock.service", "systemd/user/omarchy-sleep-lock.service"),
("default/systemd/user/omarchy-recover-internal-monitor.service", "/usr/lib/systemd/user/omarchy-recover-internal-monitor.service", "systemd/user/omarchy-recover-internal-monitor.service"),
("default/systemd/user/omarchy-update-user-notify.service", "/usr/lib/systemd/user/omarchy-update-user-notify.service", "systemd/user/omarchy-update-user-notify.service"),
("default/systemd/user/omarchy-update-user-notify.path", "/usr/lib/systemd/user/omarchy-update-user-notify.path", "systemd/user/omarchy-update-user-notify.path"),
("default/fonts/omarchy/omarchy.ttf", "/usr/share/fonts/omarchy/omarchy.ttf", "omarchy.ttf"),
]
@@ -116,6 +119,13 @@ for source, destination, legacy in package_defaults:
if destination and (source not in pkgbuild or destination not in pkgbuild):
errors.append(f"PKGBUILD does not explicitly install {source} -> {destination}")
guard_hook = "default/libalpm/hooks/00-omarchy-update-guard.hook"
guard_destination = "/usr/share/libalpm/hooks/00-omarchy-update-guard.hook"
if not (root / guard_hook).exists():
errors.append(f"missing package default source: {guard_hook}")
if guard_hook not in omarchy_pkgbuild or guard_destination not in omarchy_pkgbuild:
errors.append(f"omarchy PKGBUILD does not install {guard_hook} -> {guard_destination}")
if errors:
print("\n".join(errors), file=sys.stderr)
sys.exit(1)
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
stub_bin="$test_tmp/bin"
test_home="$test_tmp/home"
mkdir -p "$stub_bin" "$test_home"
cat >"$stub_bin/omarchy-migrate-user" <<'SH'
#!/bin/bash
if [[ ${1:-} == "--pending" && ${OMARCHY_TEST_PENDING_MIGRATIONS:-0} == 1 ]]; then
echo 200-user.sh
exit 0
else
exit 1
fi
SH
chmod +x "$stub_bin/omarchy-migrate-user"
cat >"$stub_bin/systemd-run" <<'SH'
#!/bin/bash
exit 1
SH
chmod +x "$stub_bin/systemd-run"
run_notify() {
HOME="$test_home" \
PATH="$stub_bin:$ROOT/bin:$PATH" \
OMARCHY_TEST_PENDING_MIGRATIONS="$1" \
"$ROOT/bin/omarchy-migrate-notify"
}
run_notify 0 >"$test_tmp/not-pending.out" 2>"$test_tmp/not-pending.err"
[[ ! -s $test_tmp/not-pending.out ]] || fail "migration notifier stays quiet on stdout without pending migrations"
[[ ! -s $test_tmp/not-pending.err ]] || fail "migration notifier stays quiet on stderr without pending migrations"
pass "migration notifier ignores users with no pending migrations"
run_notify 1 >"$test_tmp/pending.out" 2>"$test_tmp/pending.err"
grep -q 'Omarchy has pending user migrations' "$test_tmp/pending.err" || fail "migration notifier explains pending migrations without notification system"
grep -q 'user/200-user.sh' "$test_tmp/pending.err" || fail "migration notifier lists pending migration names"
pass "migration notifier reports pending user migrations"
+115
View File
@@ -0,0 +1,115 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
test_root="$test_tmp/omarchy"
test_home="$test_tmp/home"
system_state="$test_tmp/system-state"
mkdir -p "$test_root/migrations/system" "$test_root/migrations/user" "$test_home" "$system_state"
cat >"$test_root/migrations/system/100-system.sh" <<'SH'
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
echo system >>"$TEST_CALLS"
SH
cat >"$test_root/migrations/user/200-user.sh" <<'SH'
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
echo user >>"$TEST_CALLS"
SH
calls="$test_tmp/calls"
if ! HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate-user" --pending >"$test_tmp/user-pending.out"; then
fail "user migration runner reports pending migrations before state exists"
fi
grep -q '^200-user\.sh$' "$test_tmp/user-pending.out" || fail "user migration runner lists pending migration filename"
pass "user migration runner detects pending migrations"
HOME="$test_home" \
OMARCHY_PATH="$test_root" \
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
TEST_CALLS="$calls" \
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-first.out"
[[ $(grep -c '^user$' "$calls") -eq 1 ]] || fail "user migration runner runs user migrations"
! grep -q '^system$' "$calls" || fail "user migration runner does not run system migrations"
[[ -f $test_home/.local/state/omarchy/migrations/user/200-user.sh ]] || fail "user migration runner records user migration marker"
pass "user migration runner only runs user migrations"
HOME="$test_home" \
OMARCHY_PATH="$test_root" \
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
TEST_CALLS="$calls" \
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-second.out"
[[ $(grep -c '^user$' "$calls") -eq 1 ]] || fail "user migration runner skips completed migrations"
pass "user migration runner skips completed migrations"
if HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate-user" --pending >"$test_tmp/user-not-pending.out"; then
fail "user migration runner reports no pending migrations after state exists"
fi
pass "user migration runner detects no pending migrations"
if ! OMARCHY_PATH="$test_root" OMARCHY_SYSTEM_MIGRATION_STATE="$system_state" "$ROOT/bin/omarchy-migrate-system" --pending >"$test_tmp/system-pending.out"; then
fail "system migration runner reports pending migrations before state exists"
fi
grep -q '^100-system\.sh$' "$test_tmp/system-pending.out" || fail "system migration runner lists pending migration filename"
OMARCHY_PATH="$test_root" \
OMARCHY_SYSTEM_MIGRATION_STATE="$system_state" \
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
TEST_CALLS="$calls" \
"$ROOT/bin/omarchy-migrate-system" >"$test_tmp/system-first.out"
[[ $(grep -c '^system$' "$calls") -eq 1 ]] || fail "system migration runner runs system migrations"
[[ -f $system_state/100-system.sh ]] || fail "system migration runner records system migration marker"
pass "system migration runner only runs system migrations"
if OMARCHY_PATH="$test_root" OMARCHY_SYSTEM_MIGRATION_STATE="$system_state" "$ROOT/bin/omarchy-migrate-system" --pending >"$test_tmp/system-not-pending.out"; then
fail "system migration runner reports no pending migrations after state exists"
fi
pass "system migration runner detects no pending migrations"
failure_root="$test_tmp/failure-omarchy"
failure_home="$test_tmp/failure-home"
failure_system_state="$test_tmp/failure-system-state"
mkdir -p "$failure_root/migrations/system" "$failure_root/migrations/user" "$failure_home" "$failure_system_state"
cat >"$failure_root/migrations/user/300-fail-user.sh" <<'SH'
echo user-before-fail >>"$TEST_CALLS"
false
echo user-after-fail >>"$TEST_CALLS"
SH
set +e
HOME="$failure_home" \
OMARCHY_PATH="$failure_root" \
TEST_CALLS="$calls" \
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-failure.out" 2>"$test_tmp/user-failure.err"
user_failure_status=$?
set -e
[[ $user_failure_status -ne 0 ]] || fail "user migration runner exits non-zero when a migration fails"
[[ ! -f $failure_home/.local/state/omarchy/migrations/user/300-fail-user.sh ]] || fail "user migration runner does not mark failed migration complete"
grep -q '^user-before-fail$' "$calls" || fail "user migration runner started failing migration"
! grep -q '^user-after-fail$' "$calls" || fail "user migration runner stops failing migration under strict mode"
pass "user migration runner does not mark failed migrations complete"
cat >"$failure_root/migrations/system/400-fail-system.sh" <<'SH'
echo system-before-fail >>"$TEST_CALLS"
false
echo system-after-fail >>"$TEST_CALLS"
SH
set +e
OMARCHY_PATH="$failure_root" \
OMARCHY_SYSTEM_MIGRATION_STATE="$failure_system_state" \
TEST_CALLS="$calls" \
"$ROOT/bin/omarchy-migrate-system" >"$test_tmp/system-failure.out" 2>"$test_tmp/system-failure.err"
system_failure_status=$?
set -e
[[ $system_failure_status -ne 0 ]] || fail "system migration runner exits non-zero when a migration fails"
[[ ! -f $failure_system_state/400-fail-system.sh ]] || fail "system migration runner does not mark failed migration complete"
grep -q '^system-before-fail$' "$calls" || fail "system migration runner started failing migration"
! grep -q '^system-after-fail$' "$calls" || fail "system migration runner stops failing migration under strict mode"
pass "system migration runner does not mark failed migrations complete"
+70
View File
@@ -0,0 +1,70 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
stub_bin="$test_tmp/bin"
test_home="$test_tmp/home"
mkdir -p "$stub_bin" "$test_home"
cat >"$stub_bin/omarchy-migrate-system" <<'SH'
#!/bin/bash
if [[ ${1:-} == "--pending" ]]; then
[[ ${OMARCHY_TEST_PENDING_SYSTEM:-1} == 1 ]] || exit 1
echo 100-system.sh
exit 0
fi
echo system >>"$TEST_CALLS"
SH
chmod +x "$stub_bin/omarchy-migrate-system"
cat >"$stub_bin/omarchy-migrate-user" <<'SH'
#!/bin/bash
if [[ ${1:-} == "--pending" ]]; then
[[ ${OMARCHY_TEST_PENDING_USER:-1} == 1 ]] || exit 1
echo 200-user.sh
exit 0
fi
echo user >>"$TEST_CALLS"
SH
chmod +x "$stub_bin/omarchy-migrate-user"
run_migrate() {
HOME="$test_home" \
PATH="$stub_bin:$PATH" \
TEST_CALLS="$test_tmp/calls" \
"$ROOT/bin/omarchy-migrate" "$@"
}
: >"$test_tmp/calls"
run_migrate >"$test_tmp/migrate.out"
[[ $(sed -n '1p' "$test_tmp/calls") == "system" ]] || fail "omarchy-migrate runs system migrations first"
[[ $(sed -n '2p' "$test_tmp/calls") == "user" ]] || fail "omarchy-migrate runs user migrations second"
[[ $(wc -l <"$test_tmp/calls") -eq 2 ]] || fail "omarchy-migrate only delegates to system and user migration runners"
pass "omarchy-migrate runs system and user migrations without force"
run_migrate --pending >"$test_tmp/pending-all.out"
grep -q '^system/100-system\.sh$' "$test_tmp/pending-all.out" || fail "omarchy-migrate --pending lists pending system migrations"
grep -q '^user/200-user\.sh$' "$test_tmp/pending-all.out" || fail "omarchy-migrate --pending lists pending user migrations"
pass "omarchy-migrate --pending lists all pending migrations"
run_migrate --pending user >"$test_tmp/pending-user.out"
grep -q '^user/200-user\.sh$' "$test_tmp/pending-user.out" || fail "omarchy-migrate --pending user lists user migrations"
! grep -q '^system/' "$test_tmp/pending-user.out" || fail "omarchy-migrate --pending user omits system migrations"
pass "omarchy-migrate --pending user scopes pending output"
if OMARCHY_TEST_PENDING_SYSTEM=0 OMARCHY_TEST_PENDING_USER=0 run_migrate --pending >"$test_tmp/not-pending.out"; then
fail "omarchy-migrate --pending exits non-zero without pending migrations"
fi
[[ ! -s $test_tmp/not-pending.out ]] || fail "omarchy-migrate --pending stays quiet without pending migrations"
pass "omarchy-migrate --pending reports no pending migrations"
if run_migrate --force >"$test_tmp/force.out" 2>&1; then
fail "omarchy-migrate rejects obsolete --force option"
fi
grep -q 'Unknown option: --force' "$test_tmp/force.out" || fail "omarchy-migrate reports obsolete --force option"
pass "omarchy-migrate no longer needs --force"
+120
View File
@@ -0,0 +1,120 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
stub_bin="$test_tmp/bin"
test_home="$test_tmp/home"
state_home="$test_tmp/state"
mkdir -p "$stub_bin" "$test_home" "$state_home"
cat >"$stub_bin/fakeroot" <<'SH'
#!/bin/bash
exit 0
SH
chmod +x "$stub_bin/fakeroot"
cat >"$stub_bin/checkupdates" <<'SH'
#!/bin/bash
case "${TEST_CHECKUPDATES:-updates}" in
updates)
printf 'linux 6.1-1 -> 6.1-2\nomarchy 4.0.0-1 -> 4.0.1-1\n'
exit 0
;;
none)
exit 2
;;
fail)
echo "check failed" >&2
exit 1
;;
esac
SH
chmod +x "$stub_bin/checkupdates"
cat >"$stub_bin/pacman" <<'SH'
#!/bin/bash
case "$1" in
-Qem)
[[ ${TEST_AUR_INSTALLED:-0} == "1" ]] && exit 0 || exit 1
;;
-Qu)
if [[ ${TEST_PACMAN_FALLBACK_UPDATES:-0} == "1" ]]; then
echo "fallback-pkg 1-1 -> 1-2"
fi
exit 0
;;
esac
exit 0
SH
chmod +x "$stub_bin/pacman"
cat >"$stub_bin/yay" <<'SH'
#!/bin/bash
if [[ ${TEST_YAY_UPDATES:-0} == "1" ]]; then
echo "aur-helper 1-1 -> 1-2"
fi
exit 0
SH
chmod +x "$stub_bin/yay"
run_checker() {
HOME="$test_home" \
XDG_STATE_HOME="$state_home" \
PATH="$stub_bin:$PATH" \
OMARCHY_UPDATE_CHECK_TIMEOUT=5 \
"$ROOT/bin/omarchy-update-available"
}
capture_checker() {
local stdout_file="$1"
local stderr_file="$2"
shift 2
set +e
(
export "$@"
run_checker
) >"$stdout_file" 2>"$stderr_file"
local status=$?
set -e
return "$status"
}
stdout="$test_tmp/stdout"
stderr="$test_tmp/stderr"
if capture_checker "$stdout" "$stderr" TEST_CHECKUPDATES=updates TEST_AUR_INSTALLED=0; then
status=0
else
status=$?
fi
[[ $status -eq 0 ]] || fail "update checker exits successfully when system updates are available"
grep -q '^linux ' "$stdout" || fail "update checker prints system package updates"
grep -q '^omarchy ' "$state_home/omarchy/updates/packages" || fail "update checker stores system package updates"
[[ $(wc -l <"$state_home/omarchy/updates/available") -eq 2 ]] || fail "update checker stores combined update list"
pass "update checker detects system package updates"
if capture_checker "$stdout" "$stderr" TEST_CHECKUPDATES=none TEST_AUR_INSTALLED=1 TEST_YAY_UPDATES=1; then
status=0
else
status=$?
fi
[[ $status -eq 0 ]] || fail "update checker exits successfully when AUR updates are available"
grep -q '^aur-helper ' "$stdout" || fail "update checker prints AUR package updates"
grep -q '^aur-helper ' "$state_home/omarchy/updates/aur" || fail "update checker stores AUR package updates"
pass "update checker detects AUR package updates"
if capture_checker "$stdout" "$stderr" TEST_CHECKUPDATES=none TEST_AUR_INSTALLED=0; then
status=0
else
status=$?
fi
[[ $status -eq 1 ]] || fail "update checker exits non-zero when no updates are available"
grep -q '^System is up to date$' "$stdout" || fail "update checker prints up-to-date message"
[[ ! -s "$state_home/omarchy/updates/available" ]] || fail "update checker clears combined update list when up to date"
pass "update checker reports up-to-date systems"
+101
View File
@@ -0,0 +1,101 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
stub_bin="$test_tmp/bin"
test_home="$test_tmp/home"
runtime_dir="$test_tmp/runtime"
mkdir -p "$stub_bin" "$test_home" "$runtime_dir"
run_with_lock_env() {
HOME="$test_home" \
XDG_RUNTIME_DIR="$runtime_dir" \
XDG_STATE_HOME="$test_tmp/state" \
PATH="$stub_bin:$ROOT/bin:$PATH" \
"$@"
}
write_stub() {
local name="$1"
local body="$2"
cat >"$stub_bin/$name" <<SH
#!/bin/bash
$body
SH
chmod +x "$stub_bin/$name"
}
for command in \
omarchy-toggle-idle \
systemd-inhibit \
omarchy-update-keyring \
omarchy-update-system-pkgs \
omarchy-migrate \
omarchy-update-aur-pkgs \
omarchy-update-mise \
omarchy-update-orphan-pkgs \
omarchy-hook \
omarchy-update-analyze-logs \
omarchy-shell \
omarchy-update-restart; do
write_stub "$command" 'exit 0'
done
write_stub omarchy-update-available 'exit 1'
# omarchy-update should hold the lock before snapshotting, so a second update
# cannot even enter its pre-update snapshot.
update_snapshot_marker="$test_tmp/update-snapshot-started"
write_stub omarchy-snapshot 'echo started >"$TEST_MARKER"; sleep 2; exit 0'
OMARCHY_UPDATE_LOGGED=1 TEST_MARKER="$update_snapshot_marker" run_with_lock_env "$ROOT/bin/omarchy-update" -y >"$test_tmp/update-first.out" 2>&1 &
update_pid=$!
for _ in {1..50}; do
[[ -f $update_snapshot_marker ]] && break
sleep 0.05
done
[[ -f $update_snapshot_marker ]] || fail "first omarchy-update reached snapshot under lock"
set +e
OMARCHY_UPDATE_LOGGED=1 TEST_MARKER="$test_tmp/update-second-snapshot-started" run_with_lock_env "$ROOT/bin/omarchy-update" -y >"$test_tmp/update-second.out" 2>&1
update_second_status=$?
set -e
wait "$update_pid"
[[ $update_second_status -ne 0 ]] || fail "second omarchy-update exits non-zero while update lock is held"
grep -q "already running" "$test_tmp/update-second.out" || fail "second omarchy-update reports held update lock"
[[ ! -f $test_tmp/update-second-snapshot-started ]] || fail "second omarchy-update did not snapshot while lock was held"
pass "omarchy-update prevents overlapping top-level updates"
# omarchy-update-perform is now only a compatibility wrapper around
# omarchy-update -y, but it should still respect the same update lock.
perform_marker="$test_tmp/perform-started"
write_stub omarchy-update-keyring 'echo started >"$TEST_MARKER"; sleep 2; exit 0'
TEST_MARKER="$perform_marker" run_with_lock_env "$ROOT/bin/omarchy-update-perform" >"$test_tmp/perform-first.out" 2>&1 &
perform_pid=$!
for _ in {1..50}; do
[[ -f $perform_marker ]] && break
sleep 0.05
done
[[ -f $perform_marker ]] || fail "first omarchy-update-perform delegated to update under lock"
set +e
TEST_MARKER="$test_tmp/perform-second-started" run_with_lock_env "$ROOT/bin/omarchy-update-perform" >"$test_tmp/perform-second.out" 2>&1
perform_second_status=$?
set -e
wait "$perform_pid"
[[ $perform_second_status -ne 0 ]] || fail "second omarchy-update-perform exits non-zero while update lock is held"
grep -q "already running" "$test_tmp/perform-second.out" || fail "second omarchy-update-perform reports held update lock"
[[ ! -f $test_tmp/perform-second-started ]] || fail "second omarchy-update-perform did not snapshot while lock was held"
pass "omarchy-update-perform compatibility wrapper respects update lock"
+41
View File
@@ -0,0 +1,41 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
stub_bin="$test_tmp/bin"
test_home="$test_tmp/home"
mkdir -p "$stub_bin" "$test_home"
write_stub() {
local name="$1"
local body="$2"
cat >"$stub_bin/$name" <<SH
#!/bin/bash
$body
SH
chmod +x "$stub_bin/$name"
}
run_orphan_checker() {
HOME="$test_home" PATH="$stub_bin:$PATH" "$ROOT/bin/omarchy-update-orphan-pkgs"
}
write_stub pacman 'if [[ $1 == "-Qtdq" ]]; then printf "old-lib\nunused-tool\n"; exit 0; fi; exit 1'
write_stub sudo 'echo "sudo should not be called" >&2; exit 99'
write_stub gum 'echo "gum should not be called" >&2; exit 99'
run_orphan_checker >"$test_tmp/noninteractive.out" 2>"$test_tmp/noninteractive.err"
grep -q '^ old-lib$' "$test_tmp/noninteractive.out" || fail "orphan checker lists orphan packages"
grep -q 'Re-run omarchy-update-orphan-pkgs in a terminal' "$test_tmp/noninteractive.out" || fail "orphan checker does not remove packages non-interactively"
pass "orphan checker only reports orphans non-interactively"
write_stub pacman 'if [[ $1 == "-Qtdq" ]]; then exit 0; fi; exit 1'
run_orphan_checker >"$test_tmp/none.out" 2>"$test_tmp/none.err"
[[ ! -s $test_tmp/none.out ]] || fail "orphan checker stays quiet when no orphans exist"
pass "orphan checker stays quiet without orphans"
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
run_guard() {
OMARCHY_PACMAN_CMDLINE="$1" "$ROOT/bin/omarchy-update-pacman-guard"
}
if run_guard "pacman -Syu --noconfirm" >"$test_tmp/direct.out" 2>"$test_tmp/direct.err"; then
fail "pacman guard blocks direct system upgrades"
fi
grep -q 'omarchy update' "$test_tmp/direct.err" || fail "pacman guard explains omarchy update entrypoint"
pass "pacman guard blocks direct pacman -Syu"
if run_guard "pacman --sync --refresh --sysupgrade" >"$test_tmp/long.out" 2>"$test_tmp/long.err"; then
fail "pacman guard blocks long-form system upgrades"
fi
pass "pacman guard blocks long-form pacman sysupgrade"
OMARCHY_UPDATE_PACMAN=1 run_guard "pacman -Syu --noconfirm" >"$test_tmp/omarchy.out" 2>"$test_tmp/omarchy.err"
[[ ! -s $test_tmp/omarchy.err ]] || fail "pacman guard stays quiet for omarchy update pacman call"
pass "pacman guard allows omarchy update pacman call"
OMARCHY_ALLOW_DIRECT_PACMAN=1 run_guard "pacman -Syu --noconfirm" >"$test_tmp/override.out" 2>"$test_tmp/override.err"
[[ ! -s $test_tmp/override.err ]] || fail "pacman guard stays quiet for explicit direct pacman override"
pass "pacman guard allows explicit direct pacman override"
run_guard "pacman -S firefox" >"$test_tmp/install.out" 2>"$test_tmp/install.err"
[[ ! -s $test_tmp/install.err ]] || fail "pacman guard stays quiet for non-sysupgrade pacman command"
pass "pacman guard ignores non-system-upgrade transactions"