N?? / show marks the upstream candidate with "*" instead of ">" (the
prompt, which read as a command in logs), and every line but the note
gets a two-character gutter: " " for the installed record, "* " for the
candidate, so keys and colons line up. The plain native fallback (zypper,
unmergeable records) and the not-installed candidate use the same gutter.
pacman records (-Qi with -Si or the AUR helper's -Sia) are now compared
the way they are meant:
- values unwrapped (continuation lines joined, runs of blanks as one):
yay wraps Depends On / Optional Deps at 80 columns even without a
terminal unless COLUMNS=0, which the helper now gets for -Qua and -Sia
- Depends On, Provides, Conflicts With, Make/Check Deps and the other
lists as sets of exact tokens in any order (a constraint is a change)
- Optional Deps by package names ("name: description [installed]" in
-Qi, bare names from the AUR)
- a differing value is one line like -Qi, Optional Deps one entry per
line; candidate-only fields sit next to their counterpart (Repository
after Version, AUR URL after URL, Maintainer after Packager, ...)
Verified on recorded claude-desktop records (paru 2.1.0, yay 13.0.1, the
installed 2.9939.4-1 from the AUR's own .SRCINFO); discovery/pacman.md
section 15.2.
181 lines
8.5 KiB
Bash
181 lines
8.5 KiB
Bash
#!/usr/bin/env bats
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# Copyright (C) 2026 Bryan Joshua Pedini
|
|
|
|
# E2E: AUR packages. pacman backend (archlinux): su-dummy-aur 1.0 is a foreign package (fixture
|
|
# FIXTURE_AUR=1), the fake paru (fixtures/fake-paru.sh) offers it at 2.0 and installs it through
|
|
# the fake sudo (fixtures/fake-sudo.sh: su, passwordless for wheel). The applet runs either as the
|
|
# test user su-tester, re-executing itself through that sudo, or as root with SUDO_USER=su-tester
|
|
# (what the re-exec leaves behind). Rows: [1] su-dummy-a [2]* su-dummy-aur [3] su-dummy-b
|
|
# [4] su-dummy-c. Other backends: the marker column is a space and no AUR helper ever runs.
|
|
|
|
load helpers
|
|
|
|
PARU_LOG=/tmp/su-aur-paru.log
|
|
AUR_OLD=/srv/su-aur/su-dummy-aur-1.0-1-any.pkg.tar.zst
|
|
|
|
setup_file() {
|
|
e2e_setup_file
|
|
if [[ $BE == pacman ]]; then
|
|
install -m 0755 "$BATS_TEST_DIRNAME/fixtures/fake-paru.sh" /usr/local/bin/paru
|
|
install -m 0755 "$BATS_TEST_DIRNAME/fixtures/fake-sudo.sh" /usr/local/bin/sudo
|
|
else
|
|
# a paru that only records that it ran (it never may: AUR helpers are for pacman only)
|
|
printf '#!/bin/sh\necho "$*" >>%s\n' "$PARU_LOG" >/usr/local/bin/paru
|
|
chmod 0755 /usr/local/bin/paru
|
|
fi
|
|
}
|
|
teardown_file() {
|
|
rm -f /usr/local/bin/paru "$PARU_LOG"
|
|
if [[ $BE == pacman ]]; then rm -f /usr/local/bin/sudo; fi
|
|
}
|
|
setup() {
|
|
e2e_reset
|
|
if [[ $BE == pacman ]]; then
|
|
pacman -U --noconfirm "$AUR_OLD" >/dev/null 2>&1
|
|
[[ $(pkg_ver su-dummy-aur) == 1.0 ]]
|
|
fi
|
|
: >"$PARU_LOG"
|
|
chmod 0666 "$PARU_LOG"
|
|
}
|
|
|
|
# as_tester ARGS...: run skeptical-updater as the unprivileged su-tester (its TMPDIR: the suite's
|
|
# is root's); a run that needs root re-executes itself through the fake sudo
|
|
as_tester() { runuser -u su-tester -- env TMPDIR=/tmp HOME=/home/su-tester skeptical-updater "$@"; }
|
|
pacman_only() { [[ $BE == pacman ]] || skip "pacman backend only"; }
|
|
|
|
@test "AUR: the row is listed with * and repo aur; paru ran as the invoking user after the sudo re-exec" {
|
|
pacman_only
|
|
run as_tester list
|
|
assert_success
|
|
assert_line --index 0 "Backend: pacman ($(pretty_name)) + AUR via paru"
|
|
assert_line 'Refreshing package lists... done.'
|
|
assert_line '4 upgradable, 0 trusted (hidden, use --all to show), 4 to review:'
|
|
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
|
|
assert_line ' [2]* su-dummy-aur 1.0-1 -> 2.0-1 aur'
|
|
assert_line ' [3] su-dummy-b 1.0-1 -> 2.0-1 su-dummy'
|
|
assert_line ' [4] su-dummy-c 1.0-1 -> 2.0-1 su-dummy'
|
|
run cat "$PARU_LOG"
|
|
assert_output 'su-tester HOME=/home/su-tester PWD=/home/su-tester -Qua'
|
|
}
|
|
|
|
@test "AUR: N? and N?? on the AUR row (pacman -Qi; merged with paru -Sia)" {
|
|
pacman_only
|
|
SUDO_USER=su-tester run skeptical-updater --no-refresh <<<$'2?\n2??\nq'
|
|
assert_success
|
|
assert_output --partial "$(printf '%s\n' \
|
|
'su-dummy-aur: Skeptical-updater dummy package AUR (foreign: in no repository)' \
|
|
'reason: explicitly installed' \
|
|
'required by: nothing')"
|
|
assert_line '# lines starting with * come from the upstream candidate: a differing value, or a field the installed record lacks'
|
|
assert_output --partial "$(printf '%s\n' ' Version : 1.0-1' '* Version : 2.0-1' '* Repository : aur')"
|
|
assert_line ' Install Reason : Explicitly installed'
|
|
assert_output --partial "$(printf '%s\n' ' URL : https://example.invalid/su-dummy' '* AUR URL : https://aur.archlinux.org/packages/su-dummy-aur')"
|
|
assert_output --partial "$(printf '%s\n' ' Packager : su-fixture <su-fixture@example.invalid>' '* Maintainer : su-fixture')"
|
|
assert_output --partial "$(printf '%s\n' ' Validated By : None' '* Votes : 7' '* Popularity : 0.01' '* Out Of Date : No')"
|
|
run grep -c 'su-tester HOME=/home/su-tester PWD=/home/su-tester -Sia su-dummy-aur' "$PARU_LOG"
|
|
assert_output 1
|
|
}
|
|
|
|
@test "AUR: N- keeps su-dummy-aur at 1.0 while the repository packages upgrade; paru is not run" {
|
|
pacman_only
|
|
SUDO_USER=su-tester run skeptical-updater <<<$'2-\n'
|
|
assert_success
|
|
assert_line 'Excluded from this run: su-dummy-aur'
|
|
assert_line 'Upgrade finished.'
|
|
[[ $(versions) == "a=2.0 b=2.0 c=2.0" ]] || fail "versions after the run: $(versions)"
|
|
[[ $(pkg_ver su-dummy-aur) == 1.0 ]] || fail "su-dummy-aur: $(pkg_ver su-dummy-aur)"
|
|
run grep -c -- '-Sua' "$PARU_LOG"
|
|
assert_output 0
|
|
}
|
|
|
|
@test "AUR: a plain <enter> upgrades su-dummy-aur to 2.0 with paru, after the repository packages" {
|
|
pacman_only
|
|
run as_tester <<<''
|
|
assert_success
|
|
assert_line 'Excluded from this run: none'
|
|
assert_line '+ runuser -u su-tester -- env HOME=/home/su-tester paru -Sua --noconfirm'
|
|
assert_line 'Upgrade finished.'
|
|
[[ $(versions) == "a=2.0 b=2.0 c=2.0" ]] || fail "versions after the run: $(versions)"
|
|
[[ $(pkg_ver su-dummy-aur) == 2.0 ]] || fail "su-dummy-aur: $(pkg_ver su-dummy-aur)"
|
|
# the repository step came first: su-dummy-a was 2.0 already when paru -Sua started
|
|
run grep -A1 -- ' -Sua --noconfirm$' "$PARU_LOG"
|
|
assert_line --index 0 'su-tester HOME=/home/su-tester PWD=/home/su-tester -Sua --noconfirm'
|
|
assert_line --index 1 ' (at -Sua: su-dummy-a 2.0-1)'
|
|
run skeptical-updater list --no-refresh --no-aur
|
|
assert_output --partial 'Nothing to upgrade.'
|
|
SUDO_USER=su-tester run skeptical-updater list --no-refresh
|
|
assert_output --partial 'Nothing to upgrade.'
|
|
}
|
|
|
|
@test "AUR: only the AUR row left to upgrade: pacman is not run, only paru" {
|
|
pacman_only
|
|
# (the files only: `..` changes with the db.lck of paru's pacman -U)
|
|
before=$(ls -l --time-style=full-iso /var/lib/pacman/sync)
|
|
SUDO_USER=su-tester run skeptical-updater <<<$'1- 3- 4-\n'
|
|
assert_success
|
|
assert_line 'No repository package to upgrade: pacman is not run, only paru.'
|
|
assert_line '+ runuser -u su-tester -- env HOME=/home/su-tester paru -Sua --noconfirm --ignore su-dummy-a,su-dummy-b,su-dummy-c'
|
|
refute_line --regexp '^\+ pacman '
|
|
[[ $(versions) == "a=1.0 b=1.0 c=1.0" ]] || fail "versions after the run: $(versions)"
|
|
[[ $(pkg_ver su-dummy-aur) == 2.0 ]] || fail "su-dummy-aur: $(pkg_ver su-dummy-aur)"
|
|
[[ $(ls -l --time-style=full-iso /var/lib/pacman/sync) == "$before" ]] || fail "the sync database changed although pacman was not run"
|
|
}
|
|
|
|
@test "AUR: --dry-run prints paru's command line (as the invoking user) and changes nothing" {
|
|
pacman_only
|
|
SUDO_USER=su-tester run skeptical-updater --dry-run --no-refresh <<<$'3-\n'
|
|
assert_success
|
|
assert_line '+ pacman -Su --noconfirm --ignore su-dummy-b'
|
|
assert_line '+ runuser -u su-tester -- env HOME=/home/su-tester paru -Sua --noconfirm --ignore su-dummy-b'
|
|
assert_line 'Dry run: nothing was changed.'
|
|
[[ $(versions) == "a=1.0 b=1.0 c=1.0" && $(pkg_ver su-dummy-aur) == 1.0 ]]
|
|
run grep -c -- '-Sua' "$PARU_LOG"
|
|
assert_output 0
|
|
}
|
|
|
|
@test "AUR: unprivileged list --no-refresh runs paru directly, as that user" {
|
|
pacman_only
|
|
run as_tester list --no-refresh
|
|
assert_success
|
|
assert_line ' [2]* su-dummy-aur 1.0-1 -> 2.0-1 aur'
|
|
run cat "$PARU_LOG"
|
|
assert_output --regexp '^su-tester HOME=/home/su-tester PWD=[^ ]+ -Qua$'
|
|
}
|
|
|
|
@test "AUR: a root login (no SUDO_USER): skipped with a warning, the repository rows listed, paru never run" {
|
|
pacman_only
|
|
run skeptical-updater list --no-refresh
|
|
assert_success
|
|
assert_line --index 0 "Backend: pacman ($(pretty_name))"
|
|
assert_line --index 1 'skeptical-updater: warning: aur: paru is never run as root and there is no invoking user (SUDO_USER is not set): AUR packages are neither listed nor upgraded (run skeptical-updater through sudo from your own account, or use --no-aur)'
|
|
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
|
|
refute_output --partial 'su-dummy-aur'
|
|
[[ ! -s $PARU_LOG ]]
|
|
}
|
|
|
|
@test "AUR: --no-aur lists the repository rows only and never runs paru" {
|
|
pacman_only
|
|
run as_tester --no-aur list --no-refresh
|
|
assert_success
|
|
assert_line --index 0 "Backend: pacman ($(pretty_name))"
|
|
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
|
|
refute_output --partial 'su-dummy-aur'
|
|
[[ ! -s $PARU_LOG ]]
|
|
}
|
|
|
|
@test "other backends: the marker column is a space; no AUR helper is ever run, --aur-helper is ignored" {
|
|
[[ $BE != pacman ]] || skip "not the pacman backend"
|
|
run skeptical-updater list --no-refresh
|
|
assert_success
|
|
assert_line --regexp '^ \[1\] su-dummy-a +1\.0(-1)? +-> +2\.0(-1)? +[^ ]+$'
|
|
run skeptical-updater --aur-helper=paru list --no-refresh
|
|
assert_success
|
|
assert_line "skeptical-updater: warning: --aur-helper=paru is ignored: AUR helpers only apply to the pacman backend (Arch Linux and derivatives)"
|
|
assert_line --regexp '^ \[3\] su-dummy-c '
|
|
run skeptical-updater --dry-run --no-refresh <<<''
|
|
assert_success
|
|
refute_output --partial 'paru'
|
|
[[ ! -s $PARU_LOG ]] || fail "paru ran: $(cat "$PARU_LOG")"
|
|
}
|