feat(aur): list and upgrade AUR packages through paru or yay on Arch

On the pacman backend, an installed AUR helper (paru, else yay;
--aur-helper=paru|yay|none, --no-aur) adds the AUR updates to the review
list. The helper never runs as root: when the tool is root through sudo it
runs as SUDO_USER (runuser -u, else sudo -u, with that user's HOME, from
that home); unprivileged it runs as is; a root login gets no AUR, with a
warning. The banner names the helper ("+ AUR via paru").

- listing: <helper> -Qua (also with --no-refresh), rows with repository
  "aur"; [ignored] is shown [held]; a failing -Qua warns and the session
  goes on with the repository rows
- every row has a marker column after the number: "*" for AUR rows, a
  space otherwise (on every backend)
- N?? merges pacman -Qi with <helper> -Sia; N?, N+, Nx stay with pacman;
  N- excludes through the helper's --ignore
- <enter>: the repository step exactly as before, then <helper> -Sua
  --ignore <excluded> as the invoking user (--noconfirm only when stdin is
  not a terminal); pacman is skipped when only AUR rows are left; a helper
  failure is reported and its status returned; --dry-run prints it
- other backends never run a helper; --aur-helper is ignored with a warning

paru 2.1.0 and yay 13.0.1 formats verified in discovery/pacman.md section
15 (proof: discovery/pacman/aur.sh). Unit tests replay the recorded output
(fake paru, yay, runuser, getent); the archlinux E2E run installs the
foreign su-dummy-aur and drives a fake paru through a fake sudo built on
passwordless su for wheel.
This commit is contained in:
bryanpedini committed 2026-10-10 15:06:18 +02:00
1 parent 875c8294bf
commit def537af58
39 files changed
+1903 -115

No files matched your search

+551
View File
@@ -0,0 +1,551 @@
#!/usr/bin/env bats
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# AUR packages on the pacman backend, through the fake paru/yay (tests/unit/fakes/paru) replaying
# the output recorded in discovery/pacman.md section 15: helper detection and overrides, the user
# the helper runs as (runuser/sudo -u, SUDO_USER, a root login), the "*" marker column, -Qua
# parsing and failures, N? / N?? / N- / N+ / Nx on an AUR row, and the upgrade (repository
# packages with pacman first, then `-Sua --ignore ...`; --noconfirm only without a terminal).
# Rows with the fake paru: [1]* pfetch [2] su-dummy-a [3]* su-dummy-aur [4] su-dummy-b
# [5] su-dummy-c (pfetch and su-dummy-aur are foreign: in no repository).
# each @test runs in its own subshell: per-test exports are intended
# shellcheck disable=SC2030,SC2031
load test_helper
setup() {
common_setup
use_fakes paru pacman runuser getent
export SKEPTICAL_UPDATER_OS_RELEASE=$FAKE_DATA/os-release-arch
# root through our sudo re-exec, invoked by alice (fake getent: uid 1000, home below)
export SUDO_USER=alice
ALICE_HOME=$FAKE_DIR/home/alice
mkdir -p "$ALICE_HOME"
AS_ALICE="runuser -u alice -- env HOME=$ALICE_HOME"
}
ROW1=' [1]* pfetch 1.10.0-1 -> 1.11.0-1 aur'
ROW2=' [2] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
ROW3=' [3]* su-dummy-aur 1.0-1 -> 2.0-1 aur'
ROW4=' [4] su-dummy-b 1.0-1 -> 2.0-1 su-dummy'
ROW5=' [5] su-dummy-c 1.0-1 -> 2.0-1 su-dummy'
# upgrade_steps: the upgrade's steps from the fake log, in order (throwaway --dbpath normalised)
upgrade_steps() {
grep -E '^(pacman -Sup --noconfirm|pacman -Su |real sync at -Su|(runuser|sudo) -u .* -Sua|paru -Sua|yay -Sua)' "$FAKE_LOG" |
sed -E 's#--dbpath /tmp/skeptical-updater-db\.[^ ]+#--dbpath DB#'
}
# ---- detection and overrides -------------------------------------------------------------------
@test "detection: paru first; the banner names the helper" {
use_fakes paru yay pacman runuser getent
run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux) + AUR via paru'
log_has 'paru -Qua'
log_lacks '^yay'
}
@test "detection: yay when paru is not installed" {
use_fakes yay pacman runuser getent
run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux) + AUR via yay'
log_has "$AS_ALICE yay -Qua"
assert_line "$ROW1"
assert_line "$ROW3"
}
@test "pman: the banner reads pman (Arch Linux) + AUR via paru" {
use_fakes pman paru pacman runuser getent
run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pman (Arch Linux) + AUR via paru'
}
@test "--aur-helper=yay picks yay although paru is installed" {
use_fakes paru yay pacman runuser getent
run skup --aur-helper=yay list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux) + AUR via yay'
log_has 'yay -Qua'
log_lacks '^paru'
run skup --aur-helper yay list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux) + AUR via yay'
}
@test "--no-aur and --aur-helper=none: no helper runs, no AUR row, plain banner" {
for opt in --no-aur --aur-helper=none; do
: >"$FAKE_LOG"
run skup "$opt" list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux)'
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
refute_output --partial 'pfetch'
log_lacks '^(paru|yay|runuser)'
done
}
@test "no helper installed: no AUR, plain banner, every row still has the marker column" {
use_fakes pacman runuser getent
run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux)'
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
log_lacks '^runuser'
}
@test "--aur-helper names a helper that is not installed: error (exit 1), nothing runs" {
use_fakes paru pacman runuser getent
run skup --aur-helper=yay list --no-refresh
assert_failure 1
assert_output --partial 'error: --aur-helper=yay: yay not found in PATH'
[[ -z $(cat "$FAKE_LOG") ]]
}
@test "--aur-helper: an unknown or empty value is a usage error" {
run skup --aur-helper=trizen list
assert_failure 1
assert_output --partial "unknown AUR helper 'trizen' (expected paru, yay or none)"
run skup --aur-helper= list
assert_failure 1
assert_output --partial '--aur-helper needs a value'
run skup list --aur-helper
assert_failure 1
assert_output --partial '--aur-helper needs a value'
[[ -z $(cat "$FAKE_LOG") ]]
}
@test "apt: no helper is ever run, even with paru in PATH; --aur-helper is ignored with a warning" {
use_fakes apt paru runuser getent
export SKEPTICAL_UPDATER_OS_RELEASE=$FAKE_DATA/os-release-debian12
run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: apt (Debian GNU/Linux 12 (bookworm))'
assert_line ' [1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo'
refute_output --partial 'aur'
run skup --aur-helper=paru list --no-refresh
assert_success
assert_output --partial 'warning: --aur-helper=paru is ignored: AUR helpers only apply to the pacman backend (Arch Linux and derivatives)'
run skup --no-aur list --no-refresh
assert_success
refute_output --partial 'warning'
log_lacks '^(paru|yay|runuser)'
}
# ---- the user the helper runs as ---------------------------------------------------------------
@test "root through sudo: the helper runs as SUDO_USER with runuser -u, that user's HOME, from that home" {
run skup list --no-refresh
assert_success
log_has "$AS_ALICE paru -Qua"
log_has "paru as: HOME=$ALICE_HOME PWD=$ALICE_HOME stdin=notty"
}
@test "root through sudo without runuser: sudo -u USER -- env HOME=..." {
use_fakes paru pacman sudo getent
run skup list --no-refresh
assert_success
log_has "sudo -u alice -- env HOME=$ALICE_HOME paru -Qua"
log_has "paru as: HOME=$ALICE_HOME PWD=$ALICE_HOME stdin=notty"
assert_line "$ROW1"
}
@test "unprivileged (list --no-refresh): the helper runs directly, as we are" {
export SKEPTICAL_UPDATER_EUID=1000
unset SUDO_USER
run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux) + AUR via paru'
log_has 'paru -Qua'
log_lacks '^(runuser|sudo)'
assert_line "$ROW1"
}
@test "a root login (no SUDO_USER): AUR skipped with a warning after the banner; repository rows listed" {
unset SUDO_USER
run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux)'
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:'
[[ $(grep -c 'warning: aur:' <<<"$output") -eq 1 ]]
log_lacks '^(paru|runuser)'
}
@test "SUDO_USER root (or another uid 0 name) or an unknown user: AUR skipped with a warning" {
for u in root toor; do
SUDO_USER=$u run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux)'
assert_output --partial "warning: aur: paru is never run as root and the invoking user ($u) is root"
done
SUDO_USER=nosuchuser run skup list --no-refresh
assert_success
assert_output --partial "warning: aur: the invoking user 'nosuchuser' (SUDO_USER) is unknown"
log_lacks '^(paru|runuser)'
}
@test "a root login: the interactive upgrade runs pacman only, no helper" {
unset SUDO_USER
run skup --no-refresh <<<''
assert_success
log_has 'pacman -Su --noconfirm'
log_lacks '^(paru|runuser)'
}
# ---- listing ------------------------------------------------------------------------------------
@test "the * marker: right after the bracket of AUR rows, a space there on the others; columns aligned" {
run skup list --no-refresh
assert_success
assert_line '5 upgradable, 0 trusted (hidden, use --all to show), 5 to review:'
assert_output --partial "$(printf '%s\n' "$ROW1" "$ROW2" "$ROW3" "$ROW4" "$ROW5")"
}
@test "the marker column stays aligned with the - and = markers" {
write_state "$HEADER" "pacman${T}su-dummy-aur${T}user${T}2026-10-09T09:40:12Z"
run skup --all --no-refresh <<<$'1-\nl\nq'
assert_success
assert_line '-[1]* pfetch 1.10.0-1 -> 1.11.0-1 aur'
assert_line '=[3]* su-dummy-aur 1.0-1 -> 2.0-1 aur'
assert_line ' [2] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
}
@test "--no-refresh still lists the AUR rows (the helper always asks the AUR)" {
run skup list --no-refresh
assert_success
log_lacks '^pacman -Sy'
log_has "$AS_ALICE paru -Qua"
assert_line "$ROW3"
}
@test "with a refresh too: AUR rows next to the rows of the reviewed databases" {
run skup list
assert_success
assert_line 'Refreshing package lists... done.'
assert_line "$ROW1"
assert_line "$ROW2"
}
@test "-Qua failing (AUR unreachable): the helper's message and a warning; repository rows listed" {
FAKE_AUR_QUA=fail run skup list --no-refresh
assert_success
assert_line --index 0 'Backend: pacman (Arch Linux) + AUR via paru'
assert_output --partial 'warning: paru: error: error sending request for url (https://aur.archlinux.org/rpc): error trying to connect'
assert_output --partial 'warning: aur: paru -Qua failed, AUR packages not listed'
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
refute_output --partial '*'
}
@test "yay -Qua failing: its multi-line message is shown without the blank lines" {
use_fakes yay pacman runuser getent
FAKE_AUR_QUA=fail run skup list --no-refresh
assert_success
assert_output --partial 'warning: yay: -> 1 error occurred:'
assert_output --partial 'dial tcp 127.0.0.1:443: connect: connection refused'
assert_output --partial 'warning: aur: yay -Qua failed, AUR packages not listed'
refute_line 'skeptical-updater: warning: yay: '
}
@test "-Qua with nothing to upgrade (exit 1, silent) is not a failure" {
FAKE_AUR_QUA=none run skup list --no-refresh
assert_success
refute_output --partial 'warning'
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
}
@test "paru marks IgnorePkg packages [ignored] (shown [held]); yay leaves them out" {
FAKE_AUR_QUA=ignored run skup list --no-refresh
assert_success
assert_line ' [1]* pfetch 1.10.0-1 -> 1.11.0-1 aur [held]'
use_fakes yay pacman runuser getent
FAKE_AUR_QUA=ignored run skup list --no-refresh
assert_success
refute_output --partial 'pfetch'
assert_line ' [2]* su-dummy-aur 1.0-1 -> 2.0-1 aur'
}
@test "yay: the age suffix ([122d13h]) is no flag; its colored root warning on stdout is no row" {
use_fakes yay pacman runuser getent
for q in fixture noise; do
FAKE_AUR_QUA=$q run skup list --no-refresh
assert_success
assert_output --partial "$(printf '%s\n' "$ROW1" "$ROW2" "$ROW3")"
refute_output --partial 'Avoid'
refute_output --partial '122d13h'
done
}
@test "devel packages: the new version is latest-commit (paru by default, yay with --devel)" {
for h in paru yay; do
use_fakes "$h" pacman runuser getent
FAKE_AUR_QUA=devel run skup list --no-refresh
assert_success
assert_line --regexp '^ \[1\]\* pfetch-git +r432\.a906ff8-1 +-> +latest-commit +aur$'
done
}
@test "a name a repository lists wins over the AUR row (moved from the AUR into a repository)" {
FAKE_AUR_QUA=dup run skup list --no-refresh
assert_success
assert_line --regexp '^ \[3\] su-dummy-b +1\.0-1 +-> +2\.0-1 +su-dummy$'
refute_output --partial '9.0-1'
}
# ---- N? N?? N+ Nx on an AUR row ---------------------------------------------------------------
@test "N? on an AUR row: description, install reason and dependents from pacman -Qi" {
run skup --no-refresh <<<$'1?\nq'
assert_success
assert_output --partial "$(printf '%s\n' '> 1?' \
'pfetch: A pretty system information tool written in POSIX sh.' \
'reason: explicitly installed' \
'required by: nothing')"
log_lacks 'paru -Si'
}
@test "N?? on an AUR row: pacman -Qi merged with paru -Sia (same key column)" {
run skup --no-refresh <<<$'1??\nq'
assert_success
log_has "$AS_ALICE paru -Sia pfetch"
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.10.0-1' '> Version : 1.11.0-1')"
assert_line 'Install Reason : Explicitly installed'
assert_line 'Description : A pretty system information tool written in POSIX sh.'
[[ $(count_lines 'Description : A pretty system information tool written in POSIX sh.') -eq 1 ]]
assert_output --partial "$(printf '%s\n' \
'> Repository : aur' \
'> AUR URL : https://aur.archlinux.org/packages/pfetch' \
'> Make Deps : None' \
'> Check Deps : None' \
'> Maintainer : yigits' \
'> Votes : 48' \
'> Popularity : 0.10344' \
'> First Submitted : Sat, 16 Jan 2021 09:13:08' \
'> Last Modified : Tue, 9 Jun 2026 22:43:50' \
'> Out Of Date : No')"
}
@test "N?? with yay: its wider key column is re-padded to pacman's" {
use_fakes yay pacman runuser getent
run skup --no-refresh <<<$'1??\nq'
assert_success
log_has "$AS_ALICE yay -Sia pfetch"
assert_output --partial "$(printf '%s\n' 'Version : 1.10.0-1' '> Version : 1.11.0-1')"
assert_line '> Repository : aur'
assert_line '> Keywords : fetch'
assert_line '> First Submitted : Sat 16 Jan 2021 09:13:08 AM UTC'
assert_line '> Out-of-date : No'
refute_output --regexp 'Repository {10,}:'
}
@test "N?? when the AUR has no record of it: the installed record alone" {
run skup --no-refresh <<<$'3??\nq'
assert_success
assert_line 'Name : su-dummy-aur'
assert_line 'Install Reason : Explicitly installed'
refute_line --regexp '^> [A-Z#]'
log_has "$AS_ALICE paru -Sia su-dummy-aur"
}
@test "N?? when the AUR record does not merge: -Qi, then the AUR record with every line marked >" {
FAKE_AUR_SIA=twice run skup --no-refresh <<<$'1??\nq'
assert_success
assert_line '# lines starting with > are the AUR record (paru -Sia) as it prints it'
refute_line --partial '# lines starting with > come from the upstream candidate'
assert_line 'Version : 1.10.0-1'
[[ $(count_lines '> Version : 1.11.0-1') -eq 2 ]]
[[ $(count_lines '> Repository : aur') -eq 2 ]]
assert_line 'Install Reason : Explicitly installed'
}
@test "show PKG for an AUR package: the same merge, the helper decided on the spot" {
run skup show pfetch
assert_success
assert_line '> Repository : aur'
assert_output --partial "$(printf '%s\n' 'Version : 1.10.0-1' '> Version : 1.11.0-1')"
export SKEPTICAL_UPDATER_EUID=1000
unset SUDO_USER
: >"$FAKE_LOG"
run skup show pfetch
assert_success
assert_line '> Maintainer : yigits'
log_has 'paru -Sia pfetch'
log_lacks '^runuser'
}
@test "show of an AUR package as a root login: one warning, the installed record" {
unset SUDO_USER
run skup show pfetch
assert_success
assert_line 'Name : pfetch'
refute_line --regexp '^> '
[[ $(grep -c 'warning: aur:' <<<"$output") -eq 1 ]]
log_lacks '^paru'
}
@test "N+ on an AUR row trusts it like any installed package (backend pacman)" {
run skup --no-refresh <<<$'1+\nl\nq'
assert_success
assert_line 'trusted pfetch'
assert_line '5 upgradable, 1 trusted (hidden, use --all to show), 4 to review:'
run cat "$STATE_FILE"
assert_line --regexp "^pacman${T}pfetch${T}user${T}${DATE_RE}\$"
}
@test "Nx on an AUR row purges it with pacman -Rns; the row leaves the list" {
run skup --no-refresh <<<$'1x\ny\nl\nq'
assert_success
log_has 'pacman -Rs --print --print-format %n -- pfetch'
assert_line 'Purge pfetch now? [y/N] y'
log_has 'pacman -Rns --noconfirm -- pfetch'
assert_line '4 upgradable, 0 trusted (hidden, use --all to show), 4 to review:'
[[ $(grep -c '^ \[1\]\* pfetch' <<<"$output") -eq 1 ]] || fail "row 1 is still listed after the purge"
assert_line ' [3]* su-dummy-aur 1.0-1 -> 2.0-1 aur'
}
# ---- the upgrade --------------------------------------------------------------------------------
@test "<enter>: the repository step first (pre-check, databases, -Su), then the helper as the invoking user" {
run skup <<<''
assert_success
assert_line 'Upgrade finished.'
run upgrade_steps
assert_output "$(printf '%s\n' \
'pacman -Sup --noconfirm --dbpath DB --print-format %n %v' \
'pacman -Su --noconfirm' \
'real sync at -Su: reviewed 1 / no-sig' \
"$AS_ALICE paru -Sua --noconfirm" \
'paru -Sua --noconfirm')"
log_has "paru as: HOME=$ALICE_HOME PWD=$ALICE_HOME stdin=notty"
}
@test "N- on an AUR row: the helper's --ignore; pacman never sees AUR names" {
run skup --no-refresh <<<$'1-\n'
assert_success
assert_line 'Excluded from this run: pfetch'
log_has 'pacman -Su --noconfirm'
assert_line "+ $AS_ALICE paru -Sua --noconfirm --ignore pfetch"
log_has 'paru -Sua --noconfirm --ignore pfetch'
log_lacks '^pacman .*--ignore'
}
@test "N- on a repository row: pacman --ignore and the helper's --ignore both get it" {
run skup --no-refresh <<<$'2-\n1-\n'
assert_success
log_has 'pacman -Su --noconfirm --ignore su-dummy-a'
log_has "$AS_ALICE paru -Sua --noconfirm --ignore pfetch,su-dummy-a"
}
@test "every AUR row excluded: the helper is not run" {
run skup --no-refresh <<<$'1-\n3-\n'
assert_success
log_has 'pacman -Su --noconfirm'
log_lacks '-Sua'
}
@test "only AUR rows left to upgrade: pacman is not run, only the helper" {
run skup <<<$'2- 4- 5-\n'
assert_success
assert_line 'No repository package to upgrade: pacman is not run, only paru.'
log_lacks '^pacman -Su'
log_lacks '^pacman -Sup --noconfirm'
log_lacks '^real sync'
log_has "$AS_ALICE paru -Sua --noconfirm --ignore su-dummy-a,su-dummy-b,su-dummy-c"
assert_line 'Upgrade finished.'
}
@test "no AUR row at all: exactly the repository upgrade as before" {
FAKE_AUR_QUA=none run skup --no-refresh <<<''
assert_success
log_has 'pacman -Su --noconfirm'
log_lacks '-Sua'
}
@test "trusted (hidden) AUR rows are upgraded by the helper too" {
write_state "$HEADER" "pacman${T}pfetch${T}user${T}2026-10-09T09:40:12Z" "pacman${T}su-dummy-aur${T}user${T}2026-10-09T09:40:12Z"
# listed: [1] su-dummy-a [2] su-dummy-b [3] su-dummy-c (both AUR rows trusted: hidden)
run skup --no-refresh <<<$'1- 2- 3-\n'
assert_success
assert_line 'No repository package to upgrade: pacman is not run, only paru.'
log_has "$AS_ALICE paru -Sua --noconfirm --ignore su-dummy-a,su-dummy-b,su-dummy-c"
}
@test "an [ignored] AUR row alone does not make pacman stand aside" {
FAKE_AUR_QUA=ignored run skup --no-refresh <<<$'2- 3- 4- 5-\n'
assert_success
log_has 'pacman -Su --noconfirm --ignore su-dummy-a,su-dummy-b,su-dummy-c'
log_lacks '-Sua'
}
@test "the helper failing after a successful repository step: reported, its exit status returned" {
FAKE_AUR_SUA_RC=1 run skup --no-refresh <<<''
assert_failure 1
log_has 'pacman -Su --noconfirm'
assert_output --partial 'error: the AUR upgrade failed: paru exited with status 1 (the repository packages were upgraded)'
refute_output --partial 'hint:'
refute_output --partial 'Upgrade finished.'
}
@test "the helper failing in an AUR-only upgrade: its exit status" {
FAKE_AUR_SUA_RC=4 run skup --no-refresh <<<$'2- 4- 5-\n'
assert_failure 4
assert_output --partial 'error: the AUR upgrade failed: paru exited with status 4'
refute_output --partial 'repository packages were upgraded'
}
@test "a failing repository step: the helper is not run" {
FAKE_PACMAN_SU_RC=1 run skup --no-refresh <<<''
assert_failure 1
assert_output --partial 'the upgrade failed: pacman exited with status 1'
log_lacks '-Sua'
FAKE_PACMAN_SUP_RC=1 run skup <<<'2-'$'\n'
assert_failure 1
log_lacks '-Sua'
}
@test "--dry-run prints the helper's command line (root through sudo: as the invoking user)" {
run skup --dry-run --no-refresh <<<$'1-\n'
assert_success
assert_line '+ pacman -Su --noconfirm'
assert_line "+ $AS_ALICE paru -Sua --noconfirm --ignore pfetch"
assert_line 'Dry run: nothing was changed.'
log_lacks '-Sua'
log_lacks '^pacman -Su '
}
@test "--dry-run unprivileged: the helper's plain command line" {
export SKEPTICAL_UPDATER_EUID=1000
unset SUDO_USER
run skup --dry-run <<<''
assert_success
assert_line '+ paru -Sua --noconfirm'
log_lacks '-Sua'
log_lacks '^(runuser|sudo)'
}
@test "on a terminal: no --noconfirm, the helper gets the terminal (its PKGBUILD review)" {
pty_skup $'3-\r\r' --no-refresh
assert_success
log_has "$AS_ALICE paru -Sua --ignore su-dummy-aur"
log_has "paru as: HOME=$ALICE_HOME PWD=$ALICE_HOME stdin=tty"
log_lacks 'noconfirm --ignore su-dummy-aur'
log_has 'pacman -Su --noconfirm'
}
@test "help and --help mention the * marker and the options" {
run skup --no-refresh <<<$'h\nq'
assert_success
assert_line " l redraw the list (a '*' after the number marks an AUR package)"
run skup --help
assert_success
assert_line --partial '--aur-helper=NAME pacman backend: list and upgrade AUR packages with paru or yay, or'
assert_line --partial '--no-aur same as --aur-helper=none'
assert_output --partial "A '*' right after the number marks an AUR package"
}
+3 -3
View File
@@ -193,7 +193,7 @@ DNF_UPGRADE='dnf -y --setopt=skip_if_unavailable=0 --setopt=*.metadata_expire=-1
assert_line 'not purged: su-dummy-b is required by: su-dummy-a - purge the dependents first'
refute_output --partial '[y/N]'
log_lacks 'purge'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
}
@test "apt: purge plan = the simulated purge minus pre-existing orphans; the target's own orphaned dependencies go too" {
@@ -529,8 +529,8 @@ REAL_SYNC_RE='/pacman-db/sync'
log_has 'dnf --assumeno remove su-dummy-a'
assert_output --partial 'Purge su-dummy-a now? This also removes: su-dummy-b [y/N]'
log_has 'dnf -y remove su-dummy-a su-dummy-b'
[[ $(grep -c '\[4\] su-dummy-b' <<<"$output") -eq 1 ]]
[[ $(grep -c '\[3\] su-dummy-a' <<<"$output") -eq 1 ]]
[[ $(grep -c '\[4\] su-dummy-b' <<<"$output") -eq 1 ]]
[[ $(grep -c '\[3\] su-dummy-a' <<<"$output") -eq 1 ]]
}
@test "dnf: belt and braces - a removal table with a non-dependency is refused" {
+1
View File
@@ -0,0 +1 @@
error: error sending request for url (https://aur.archlinux.org/rpc): error trying to connect: tcp connect error: Connection refused (os error 111): error trying to connect: tcp connect error: Connection refused (os error 111): tcp connect error: Connection refused (os error 111): Connection refused (os error 111)
+4
View File
@@ -0,0 +1,4 @@
-> 1 error occurred:
* request failed: Get "https://aur.archlinux.org/rpc?arg%5B%5D=paru&arg%5B%5D=pfetch&arg%5B%5D=su-dummy-aur&type=info&v=5": dial tcp 127.0.0.1:443: connect: connection refused
+1
View File
@@ -0,0 +1 @@
pfetch-git r432.a906ff8-1 -> latest-commit
+2
View File
@@ -0,0 +1,2 @@
pfetch 1.10.0-1 -> 1.11.0-1
su-dummy-b 1.0-1 -> 9.0-1
+2
View File
@@ -0,0 +1,2 @@
pfetch 1.10.0-1 -> 1.11.0-1
su-dummy-aur 1.0-1 -> 2.0-1
+2
View File
@@ -0,0 +1,2 @@
pfetch 1.10.0-1 -> 1.11.0-1 [ignored]
su-dummy-aur 1.0-1 -> 2.0-1
+2
View File
@@ -0,0 +1,2 @@
pfetch 1.10.0-1 -> 1.11.0-1
su-dummy-aur 1.0-1 -> 2.0-1
+1
View File
@@ -0,0 +1 @@
pfetch-git r432.a906ff8-1 -> latest-commit [2299d6h]
+2
View File
@@ -0,0 +1,2 @@
pfetch 1.10.0-1 -> 1.11.0-1 [122d13h]
su-dummy-b 1.0-1 -> 9.0-1 [1d2h]
+2
View File
@@ -0,0 +1,2 @@
pfetch 1.10.0-1 -> 1.11.0-1 [122d13h]
su-dummy-aur 1.0-1 -> 2.0-1 [3d4h]
+1
View File
@@ -0,0 +1 @@
su-dummy-aur 1.0-1 -> 2.0-1 [3d4h]
+3
View File
@@ -0,0 +1,3 @@
 -> Avoid running yay as root/sudo.
pfetch 1.10.0-1 -> 1.11.0-1 [122d13h]
su-dummy-aur 1.0-1 -> 2.0-1 [3d4h]
+21
View File
@@ -0,0 +1,21 @@
Repository : aur
Name : pfetch
Version : 1.11.0-1
Description : A pretty system information tool written in POSIX sh.
URL : https://github.com/Un1q32/pfetch
AUR URL : https://aur.archlinux.org/packages/pfetch
Groups : None
Licenses : MIT
Provides : pfetch
Depends On : None
Make Deps : None
Check Deps : None
Optional Deps : None
Conflicts With : pfetch-git
Maintainer : yigits
Votes : 48
Popularity : 0.10344
First Submitted : Sat, 16 Jan 2021 09:13:08
Last Modified : Tue, 9 Jun 2026 22:43:50
Out Of Date : No
+23
View File
@@ -0,0 +1,23 @@
Repository : aur
Name : pfetch
Version : 1.11.0-1
Description : A pretty system information tool written in POSIX sh.
URL : https://github.com/Un1q32/pfetch
Licenses : MIT
Groups : None
Provides : pfetch
Depends On : None
Optional Deps : None
Make Deps : None
Check Deps : None
Conflicts With : pfetch-git
Replaces : None
AUR URL : https://aur.archlinux.org/packages/pfetch
First Submitted : Sat 16 Jan 2021 09:13:08 AM UTC
Keywords : fetch
Last Modified : Tue 09 Jun 2026 10:43:50 PM UTC
Maintainer : yigits
Popularity : 0.103440
Votes : 48
Out-of-date : No
+44
View File
@@ -288,3 +288,47 @@ Install Date : Sun Oct 4 00:00:00 2026
Install Reason : Installed as a dependency for another package
Install Script : No
Validated By : Signature
Name : pfetch
Version : 1.10.0-1
Description : A pretty system information tool written in POSIX sh.
Architecture : any
URL : https://github.com/Un1q32/pfetch
Licenses : MIT
Groups : None
Provides : pfetch
Depends On : None
Optional Deps : None
Required By : None
Optional For : None
Conflicts With : pfetch-git
Replaces : None
Installed Size : 81.50 KiB
Packager : Unknown Packager
Build Date : Sat Oct 10 12:42:02 2026
Install Date : Sat Oct 10 12:42:04 2026
Install Reason : Explicitly installed
Install Script : No
Validated By : None
Name : su-dummy-aur
Version : 1.0-1
Description : Skeptical-updater dummy package AUR (foreign: in no repository)
Architecture : any
URL : https://example.invalid/su-dummy
Licenses : custom
Groups : None
Provides : None
Depends On : None
Optional Deps : None
Required By : None
Optional For : None
Conflicts With : None
Replaces : None
Installed Size : 4.00 B
Packager : su-fixture <su-fixture@example.invalid>
Build Date : Tue Nov 14 22:13:20 2023
Install Date : Fri Oct 9 08:00:00 2026
Install Reason : Explicitly installed
Install Script : No
Validated By : None
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake getent (unit tests): "getent passwd NAME" for alice (uid 1000, home $FAKE_DIR/home/alice),
# root and toor (uid 0); exit 2 (no such key) for anyone else
[[ ${1:-} == passwd ]] || exit 1
case ${2:-} in
alice) echo "alice:x:1000:1000:Alice:${FAKE_DIR:?}/home/alice:/bin/bash" ;;
root) echo "root:x:0:0::/root:/bin/bash" ;;
toor) echo "toor:x:0:0:root by another name:/root:/bin/bash" ;;
*) exit 2 ;;
esac
+1 -1
View File
@@ -145,7 +145,7 @@ case $op in
fi
case $tg in
su-dummy-a) printf '%s\n' su-dummy-a su-dummy-b ;; # b was installed as a dependency of a
su-dummy-c | glib2 | expat | ca-certificates-mozilla) echo "$tg" ;;
su-dummy-c | glib2 | expat | ca-certificates-mozilla | pfetch | su-dummy-aur) echo "$tg" ;; # (the last two: foreign, AUR)
*)
echo "error: target not found: $tg" >&2
exit 1
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake paru (unit tests; fakes/yay/yay runs this file as yay): replays the output of paru 2.1.0
# and yay 13.0.1 recorded in discovery/pacman.md section 15 (tests/unit/data/aur/) and logs every
# call, followed by "<helper> as: HOME=... PWD=... stdin=tty|notty" (where and how it runs).
# FAKE_AUR_QUA selects what -Qua prints: fixture (default: pfetch and su-dummy-aur), ignored
# (pfetch in IgnorePkg: paru marks it [ignored], yay leaves it out), devel (a -git package whose
# upstream moved: "-> latest-commit"), dup (an AUR row for su-dummy-b, which a repository has),
# noise (yay's colored root warning on stdout), none (nothing to upgrade: exit 1, no output) or
# fail (the AUR is unreachable: exit 1 with the recorded error). Packages purged by the fake pacman
# are not listed. -Sia PKG prints data/aur/Sia-<helper>-PKG.txt (else the helper's not-found
# error, exit 1), twice with FAKE_AUR_SIA=twice (a record that cannot be merged); -Sua exits
# FAKE_AUR_SUA_RC (default 0).
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
fake_log "$@"
if [[ -t 0 ]]; then stdin='tty'; else stdin='notty'; fi
printf '%s as: HOME=%s PWD=%s stdin=%s\n' "$FAKE_NAME" "${HOME-}" "$PWD" "$stdin" >>"$FAKE_LOG"
D=$FAKE_DATA/aur
case ${1:-} in
-Qua)
case ${FAKE_AUR_QUA:-fixture} in
none) exit 1 ;;
fail)
cat "$D/Qua-fail-$FAKE_NAME.err" >&2
exit 1
;;
esac
out=$(
while IFS= read -r line; do
fake_purged "${line%% *}" || printf '%s\n' "$line"
done <"$D/Qua-$FAKE_NAME-${FAKE_AUR_QUA:-fixture}.txt"
)
[[ -n $out ]] || exit 1
printf '%s\n' "$out"
;;
-Sia)
if [[ -f $D/Sia-$FAKE_NAME-${2:-}.txt ]]; then
cat "$D/Sia-$FAKE_NAME-$2.txt"
[[ ${FAKE_AUR_SIA:-} != twice ]] || cat "$D/Sia-$FAKE_NAME-$2.txt"
exit 0
fi
if [[ $FAKE_NAME == yay ]]; then
echo " -> No AUR package found for ${2:-}" >&2
else
echo "error: package '${2:-}' was not found" >&2
fi
exit 1
;;
-Sua) exit "$(fake_rc FAKE_AUR_SUA_RC 0)" ;;
*)
echo "fake $FAKE_NAME: unhandled: $*" >&2
exit 99
;;
esac
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake runuser (unit tests): logs "runuser -u USER -- CMD..." and runs CMD (as the same user)
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
fake_log "$@"
if [[ ${1:-} != -u || ${3:-} != -- ]]; then
echo "fake runuser: unexpected arguments: $*" >&2
exit 98
fi
shift 3
exec "$@"
+6 -1
View File
@@ -2,8 +2,13 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake sudo (unit tests): logs the command it was asked to run, runs nothing
# fake sudo (unit tests): logs the command it was asked to run; runs nothing (the re-exec of the
# applet), except "sudo -u USER -- CMD...", which runs CMD (as the same user: an AUR helper)
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
fake_log "$@"
if [[ ${1:-} == -u && ${3:-} == -- ]]; then
shift 3
exec "$@"
fi
exit 0
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake yay (unit tests): the fake paru, replaying yay's recorded output instead
FAKE_AS=yay exec "${BASH_SOURCE[0]%/*}/../paru/paru" "$@"
+22 -22
View File
@@ -16,7 +16,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_success
assert_line --index 0 'Backend: apt (Debian GNU/Linux 12 (bookworm))'
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
assert_line ' [1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo'
assert_line '<enter> upgrade | N? what is it | N?? full info | N- exclude this run | Nx purge now | N+ trust forever'
assert_line '> q'
assert_line 'Quit: nothing was upgraded.'
@@ -81,7 +81,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
@test "N? on a new dependency (old version -) says 'not installed' without asking the package manager" {
FAKE_APT_SIM=real run skup --no-refresh <<<$'9?\nq'
assert_success
assert_line --regexp '^ \[9\] su-dummy-newdep +- +-> +1\.0 +su-fixture:su-repo$'
assert_line --regexp '^ \[9\] su-dummy-newdep +- +-> +1\.0 +su-fixture:su-repo$'
assert_output --partial "$(printf '%s\n' '> 9?' \
'su-dummy-newdep: (no description available: unknown package?)' \
'reason: not installed' \
@@ -114,8 +114,8 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_success
assert_line 'excluded from this run: su-dummy-b'
assert_line 're-included: su-dummy-b'
assert_line '-[2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line '-[2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line 'Excluded from this run: su-dummy-b'
log_has 'apt-mark hold su-dummy-b'
log_has 'apt-mark unhold su-dummy-b'
@@ -129,8 +129,8 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
log_has 'apt-get -y purge su-dummy-c'
log_lacks 'autoremove --purge'
assert_line '2 upgradable, 0 trusted (hidden, use --all to show), 2 to review:'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
[[ $(grep -c '^ \[3\] su-dummy-c' <<<"$output") -eq 1 ]]
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
[[ $(grep -c '^ \[3\] su-dummy-c' <<<"$output") -eq 1 ]]
assert_output --partial 'no package [3] in the list (l to redraw)'
}
@@ -148,7 +148,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
FAKE_APT_PURGE_RC=100 run skup --no-refresh <<<$'3x\nyes\nl\nq'
assert_success
assert_output --partial 'purge of su-dummy-c failed (apt exited 100); the row stays in the list'
assert_line ' [3] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [3] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
}
@test "Nx: EOF at the confirmation aborts with exit 2 and purges nothing" {
@@ -163,7 +163,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_line 'not purged: su-dummy-b is required by: su-dummy-a - purge the dependents first'
refute_output --partial '[y/N]'
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
[[ $(grep -c '^ \[2\] su-dummy-b' <<<"$output") -eq 2 ]]
[[ $(grep -c '^ \[2\] su-dummy-b' <<<"$output") -eq 2 ]]
log_lacks '^apt-get -y'
}
@@ -173,7 +173,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_line 'Purge su-dummy-a now? This also removes: su-dummy-b [y/N] y'
assert_line 'purged: su-dummy-a su-dummy-b'
assert_line '1 upgradable, 0 trusted (hidden, use --all to show), 1 to review:'
assert_line ' [3] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [3] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
}
@test "Nx: rows the purge took with it unannounced leave the list too (re-listed afterwards)" {
@@ -181,7 +181,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_success
assert_line ' (su-dummy-a is no longer upgradable, removed from the list)'
assert_line '1 upgradable, 0 trusted (hidden, use --all to show), 1 to review:'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
}
@test "Nx on a new dependency (old version -, not installed) is refused" {
@@ -224,10 +224,10 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_success
assert_line 'trusted su-dummy-a (+1 dependency: su-dummy-b)'
assert_line '3 upgradable, 2 trusted (hidden, use --all to show), 1 to review:'
assert_line ' [3] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [3] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
# [1] and [2] only appear in the first listing
[[ $(grep -c '^ \[1\] su-dummy-a' <<<"$output") -eq 1 ]]
[[ $(grep -c '^ \[2\] su-dummy-b' <<<"$output") -eq 1 ]]
[[ $(grep -c '^ \[1\] su-dummy-a' <<<"$output") -eq 1 ]]
[[ $(grep -c '^ \[2\] su-dummy-b' <<<"$output") -eq 1 ]]
run cut -f1-3 "$STATE_FILE"
assert_line "apt${T}su-dummy-a${T}user"
assert_line "apt${T}su-dummy-b${T}dep:su-dummy-a"
@@ -254,8 +254,8 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
run skup --no-refresh <<<$'1?\nq'
assert_success
assert_line '3 upgradable, 1 trusted (hidden, use --all to show), 2 to review:'
assert_line ' [1] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [1] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-c 1.0 -> 2.0 su-fixture:su-repo'
assert_line 'su-dummy-b: dummy package su-dummy-b for skeptical-updater tests'
}
@@ -264,11 +264,11 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
run skup --no-refresh --all <<<$'2+\nl\nq'
assert_success
assert_line '3 upgradable, 1 trusted (marked with =), 2 to review:'
assert_line '=[1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line '=[1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line 'trusted su-dummy-b'
assert_line '3 upgradable, 2 trusted (marked with =), 1 to review:'
assert_line '=[2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line '=[2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
}
@test "trusted packages are upgraded silently (never excluded)" {
@@ -305,7 +305,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_success
assert_line 'excluded all 3 listed packages from this run'
assert_line 're-included all 3 listed packages'
assert_line '-[1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo'
assert_line '-[1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo'
assert_line 'Excluded from this run: su-dummy-a su-dummy-b su-dummy-c'
log_has 'apt-mark hold su-dummy-a su-dummy-b su-dummy-c'
}
@@ -316,7 +316,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_line 'su-dummy-a: dummy package su-dummy-a for skeptical-updater tests'
assert_line 'excluded from this run: su-dummy-b'
assert_line 'su-dummy-c: dummy package su-dummy-c for skeptical-updater tests'
assert_line '-[2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line '-[2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
}
@test "an unknown token prints an error, runs nothing from that line and re-prompts" {
@@ -324,7 +324,7 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
assert_success
assert_output --partial "unknown command 'bogus' (h for help)"
assert_output --partial "unknown command '3y' (h for help)"
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
assert_line ' [2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo'
refute_output --partial 'excluded from this run'
[[ ! -e $STATE_FILE ]]
}
@@ -369,6 +369,6 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
echo su-dummy-c >"$FAKE_DIR/holds"
FAKE_APT_SIM=held run skup --no-refresh <<<$'3?\nq'
assert_success
assert_line ' [3] su-dummy-c 1.0 -> 2.0 file:/srv/su-repo ./ [held]'
assert_line ' [3] su-dummy-c 1.0 -> 2.0 file:/srv/su-repo ./ [held]'
assert_line 'su-dummy-c: dummy package su-dummy-c for skeptical-updater tests'
}
+32 -32
View File
@@ -18,16 +18,16 @@ setup() { common_setup; }
FAKE_APT_SIM=real run skup list --no-refresh
assert_success
assert_line '10 upgradable, 0 trusted (hidden, use --all to show), 10 to review:'
assert_line --regexp '^ \[1\] libaudit-common +1:3\.1\.2-2\.1build1\.1 +-> +1:3\.1\.2-2\.1ubuntu0\.1 +Ubuntu:24\.04/noble-updates$'
assert_line --regexp '^ \[2\] libaudit1 +1:3\.1\.2-2\.1build1\.1 +-> +1:3\.1\.2-2\.1ubuntu0\.1 +Ubuntu:24\.04/noble-updates$'
assert_line --regexp '^ \[3\] libc6:i386 +2\.36-9 +-> +2\.36-9\+deb12u10 +Debian-Security:12/oldstable-security, Debian:12\.12/oldstable$'
assert_line --regexp '^ \[4\] libssl3t64 +3\.0\.13-0ubuntu3\.15 +-> +3\.0\.13-0ubuntu3\.16 +Ubuntu:24\.04/noble-updates, Ubuntu:24\.04/noble-security$'
assert_line --regexp '^ \[5\] perl-base +5\.36\.0-7\+deb12u3 +-> +5\.36\.0-7\+deb12u4 +http://deb\.debian\.org/debian-security bookworm-security/main amd64 \[held\]$'
assert_line --regexp '^ \[6\] su-dummy-c +1\.0 +-> +2\.0 +file:/srv/su-repo \./ \[held\]$'
assert_line --regexp '^ \[7\] su-dummy-e +1\.0 +-> +2\.0 +file:/srv/su-repo \./ \[held\]$'
assert_line --regexp '^ \[8\] su-dummy-m +1\.0 +-> +2\.0 +su-fixture:su-repo$'
assert_line --regexp '^ \[9\] su-dummy-newdep +- +-> +1\.0 +su-fixture:su-repo$'
assert_line --regexp '^ \[10\] su-dummy-slow +0\.9 +-> +1\.0$'
assert_line --regexp '^ \[1\] libaudit-common +1:3\.1\.2-2\.1build1\.1 +-> +1:3\.1\.2-2\.1ubuntu0\.1 +Ubuntu:24\.04/noble-updates$'
assert_line --regexp '^ \[2\] libaudit1 +1:3\.1\.2-2\.1build1\.1 +-> +1:3\.1\.2-2\.1ubuntu0\.1 +Ubuntu:24\.04/noble-updates$'
assert_line --regexp '^ \[3\] libc6:i386 +2\.36-9 +-> +2\.36-9\+deb12u10 +Debian-Security:12/oldstable-security, Debian:12\.12/oldstable$'
assert_line --regexp '^ \[4\] libssl3t64 +3\.0\.13-0ubuntu3\.15 +-> +3\.0\.13-0ubuntu3\.16 +Ubuntu:24\.04/noble-updates, Ubuntu:24\.04/noble-security$'
assert_line --regexp '^ \[5\] perl-base +5\.36\.0-7\+deb12u3 +-> +5\.36\.0-7\+deb12u4 +http://deb\.debian\.org/debian-security bookworm-security/main amd64 \[held\]$'
assert_line --regexp '^ \[6\] su-dummy-c +1\.0 +-> +2\.0 +file:/srv/su-repo \./ \[held\]$'
assert_line --regexp '^ \[7\] su-dummy-e +1\.0 +-> +2\.0 +file:/srv/su-repo \./ \[held\]$'
assert_line --regexp '^ \[8\] su-dummy-m +1\.0 +-> +2\.0 +su-fixture:su-repo$'
assert_line --regexp '^ \[9\] su-dummy-newdep +- +-> +1\.0 +su-fixture:su-repo$'
assert_line --regexp '^ \[10\] su-dummy-slow +0\.9 +-> +1\.0$'
refute_output --partial 'su-dummy-f'
log_has 'apt-get -s --with-new-pkgs upgrade'
log_has 'apt-cache policy perl-base su-dummy-c su-dummy-e'
@@ -36,8 +36,8 @@ setup() { common_setup; }
@test "apt: a held package from the fixture shows up with the held flag" {
FAKE_APT_SIM=held run skup list --no-refresh
assert_success
assert_line --regexp '^ \[1\] su-dummy-a +1\.0 +-> +2\.0 +su-fixture:su-repo$'
assert_line --regexp '^ \[3\] su-dummy-c +1\.0 +-> +2\.0 +file:/srv/su-repo \./ \[held\]$'
assert_line --regexp '^ \[1\] su-dummy-a +1\.0 +-> +2\.0 +su-fixture:su-repo$'
assert_line --regexp '^ \[3\] su-dummy-c +1\.0 +-> +2\.0 +file:/srv/su-repo \./ \[held\]$'
}
@test "apt: nothing to upgrade" {
@@ -182,10 +182,10 @@ EOF
FAKE_PACMAN_QU=real run skup list --no-refresh
assert_success
assert_line '6 upgradable, 0 trusted (hidden, use --all to show), 6 to review:'
assert_line ' [1] ca-certificates-mozilla 3.130-1 -> 3.131-1 core'
assert_line --regexp '^ \[2\] expat +2\.8\.5-1 +-> +2\.9\.0-1 +core \[held\]$'
assert_line --regexp '^ \[3\] glib2 +2\.88\.3-1 +-> +2\.90\.1-1 +core \[held\]$'
assert_line --regexp '^ \[5\] su-dummy-b +1\.0-1 +-> +2\.0-1 +su-dummy$'
assert_line ' [1] ca-certificates-mozilla 3.130-1 -> 3.131-1 core'
assert_line --regexp '^ \[2\] expat +2\.8\.5-1 +-> +2\.9\.0-1 +core \[held\]$'
assert_line --regexp '^ \[3\] glib2 +2\.88\.3-1 +-> +2\.90\.1-1 +core \[held\]$'
assert_line --regexp '^ \[5\] su-dummy-b +1\.0-1 +-> +2\.0-1 +su-dummy$'
refute_output --partial 'su-dummy2'
}
@@ -194,7 +194,7 @@ EOF
FAKE_PACMAN_SL=empty run skup list --no-refresh
assert_success
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1'
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1'
}
@test "pacman: packages only the transaction (-Sup) shows become a note" {
@@ -361,14 +361,14 @@ EOF
run skup list --no-refresh
assert_success
assert_line '6 upgradable, 0 trusted (hidden, use --all to show), 6 to review:'
assert_line ' [1] gnutls 3.8.10-4.el9_8 -> 3.8.10-9.el9_8 baseos'
assert_line ' [1] gnutls 3.8.10-4.el9_8 -> 3.8.10-9.el9_8 baseos'
# installonly: the highest installed version is the old one
assert_line --regexp '^ \[2\] kernel-core +5\.14\.0-611\.5\.el9 +-> +5\.14\.0-612\.1\.el9 +baseos$'
assert_line --regexp '^ \[3\] su-dummy-a +1\.0-1 +-> +2\.0-1 +su-dummy$'
assert_line --regexp '^ \[5\] su-dummy-c +1\.0-1 +-> +2\.0-1 +su-dummy$'
assert_line --regexp '^ \[2\] kernel-core +5\.14\.0-611\.5\.el9 +-> +5\.14\.0-612\.1\.el9 +baseos$'
assert_line --regexp '^ \[3\] su-dummy-a +1\.0-1 +-> +2\.0-1 +su-dummy$'
assert_line --regexp '^ \[5\] su-dummy-c +1\.0-1 +-> +2\.0-1 +su-dummy$'
# epoch kept on both sides
assert_line --regexp '^ \[6\] vim-minimal +2:8\.2\.2637-26\.el9_8\.21 +-> +2:8\.2\.2637-26\.el9_8\.23 +baseos$'
refute_line --regexp '\] su-dummy-new'
assert_line --regexp '^ \[6\] vim-minimal +2:8\.2\.2637-26\.el9_8\.21 +-> +2:8\.2\.2637-26\.el9_8\.23 +baseos$'
refute_line --regexp '\] +su-dummy-new'
refute_output --partial 'su-dummy-old'
refute_output --partial 'Obsoleting'
assert_line 'Note: the upgrade also installs (obsoleting installed packages): su-dummy-new'
@@ -390,8 +390,8 @@ EOF
FAKE_DNF_MAJOR=5 run skup list --no-refresh
assert_success
assert_line '5 upgradable, 0 trusted (hidden, use --all to show), 5 to review:'
assert_line --regexp '^ \[1\] ca-certificates +2025\.2\.80_v9\.0\.305-91\.el9 +-> +2026\.2\.90_v9\.0\.317-1\.fc44 +updates$'
assert_line --regexp '^ \[2\] curl +8\.18\.0-1\.fc44 +-> +8\.18\.0-12\.fc44 +updates$'
assert_line --regexp '^ \[1\] ca-certificates +2025\.2\.80_v9\.0\.305-91\.el9 +-> +2026\.2\.90_v9\.0\.317-1\.fc44 +updates$'
assert_line --regexp '^ \[2\] curl +8\.18\.0-1\.fc44 +-> +8\.18\.0-12\.fc44 +updates$'
refute_output --partial 'Upgrades'
}
@@ -600,10 +600,10 @@ EOF
FAKE_ZYPPER_LU=real run skup list --no-refresh
assert_success
assert_line '4 upgradable, 0 trusted (hidden, use --all to show), 4 to review:'
assert_line ' [1] openSUSE-build-key 1.0-68.1 -> 1.0-69.1 repo-update'
assert_line --regexp '^ \[2\] su-dummy-a +1\.0-1 +-> +2\.0-1 +su-dummy$'
assert_line --regexp '^ \[3\] su-dummy-b +1\.0-1 +-> +2\.0-1 +openSUSE:repo-oss & co$'
assert_line --regexp '^ \[4\] su-dummy-c +1\.0-1 +-> +2\.0-1 +su-dummy$'
assert_line ' [1] openSUSE-build-key 1.0-68.1 -> 1.0-69.1 repo-update'
assert_line --regexp '^ \[2\] su-dummy-a +1\.0-1 +-> +2\.0-1 +su-dummy$'
assert_line --regexp '^ \[3\] su-dummy-b +1\.0-1 +-> +2\.0-1 +openSUSE:repo-oss & co$'
assert_line --regexp '^ \[4\] su-dummy-c +1\.0-1 +-> +2\.0-1 +su-dummy$'
log_has 'zypper --non-interactive --xmlout list-updates'
}
@@ -615,7 +615,7 @@ EOF
log_has 'zypper --non-interactive --no-refresh --xmlout dist-upgrade --dry-run'
log_lacks 'list-updates'
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
assert_line ' [1] su-dummy-a 1.0-1 -> 2.0-1 su-dummy'
refute_output --partial 'openSUSE-release'
}
@@ -624,7 +624,7 @@ EOF
export SKEPTICAL_UPDATER_OS_RELEASE=$FAKE_DATA/os-release-tumbleweed
FAKE_ZYPPER_DUP=removes run skup list --no-refresh
assert_success
assert_line ' [2] su-dummy-newdep - -> 1.0-1 su-dummy'
assert_line ' [2] su-dummy-newdep - -> 1.0-1 su-dummy'
assert_line 'Note: the dist-upgrade also removes: libcurl-mini4'
}
@@ -734,7 +734,7 @@ EOF
export SKEPTICAL_UPDATER_OS_RELEASE=$FAKE_DATA/os-release-tumbleweed
FAKE_ZYPPER_DUP=removes run skup --no-refresh <<<$'2?\nq'
assert_success
assert_line ' [2] su-dummy-newdep - -> 1.0-1 su-dummy'
assert_line ' [2] su-dummy-newdep - -> 1.0-1 su-dummy'
assert_line 'reason: not installed'
assert_line 'required by: nothing'
log_lacks 'zypper --non-interactive --no-refresh --quiet info su-dummy-newdep'
+1 -1
View File
@@ -249,7 +249,7 @@ setup() { common_setup; }
write_state "$HEADER" "pacman${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z"
run skup list --no-refresh
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
assert_line --regexp '^ \[1\] su-dummy-a '
assert_line --regexp '^ \[1\] su-dummy-a '
}
@test "the reason does not matter for hiding: dep rows hide too" {
+1 -1
View File
@@ -36,7 +36,7 @@ common_setup() {
export TMPDIR=$BATS_TEST_TMPDIR
export FAKE_PACMAN_DBPATH=$FAKE_DIR/pacman-db
mkdir -p "$FAKE_PACMAN_DBPATH/sync" "$FAKE_PACMAN_DBPATH/local"
unset NO_COLOR ZYPP_CONF COLUMNS SKEPTICAL_UPDATER_LOCK_WAIT
unset NO_COLOR ZYPP_CONF COLUMNS SKEPTICAL_UPDATER_LOCK_WAIT SUDO_USER
use_fakes apt
}