1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
#!/bin/bash
# audit-packages.sh — verify every package archsetup installs still exists
# at its declared source, and flag packages that moved between the official
# repos and the AUR.
#
# Extraction covers direct `pacman_install pkg` / `aur_install pkg` calls
# and `for software in a b c; do` loop lists (backslash continuations
# included). Variable arguments ("$software") are the loop plumbing, not
# packages, and are skipped.
#
# Checks:
# official package missing from sync dbs -> MOVED TO AUR (if AUR has it)
# or MISSING EVERYWHERE
# AUR package gone from the AUR -> NOW IN OFFICIAL (if repos
# have it) or MISSING EVERYWHERE
#
# Usage: audit-packages.sh [--list] [installer-script]
# --list print the extracted package lists and exit (no network)
# default audit; exit 1 when anything is missing or moved
#
# Env overrides (tests): AUDIT_PACMAN, AUDIT_CURL.
set -u
PACMAN="${AUDIT_PACMAN:-pacman}"
CURL="${AUDIT_CURL:-curl}"
mode=audit
case "${1:-}" in
--list) mode=list; shift ;;
esac
script="${1:-$(dirname "$0")/../archsetup}"
if [ ! -r "$script" ]; then
echo "audit-packages: cannot read installer script: $script" >&2
exit 2
fi
# Extract package names per source. Loop lists are attributed to the
# install command used inside the loop body.
extract() {
awk '
# Collect a `for software in ...` list (may span backslash-continued
# lines); attribute it when the loop body shows which installer runs.
/for[ \t]+[A-Za-z_]+[ \t]+in[ \t]/ {
line = $0
sub(/^.*[ \t]in[ \t]+/, "", line)
listpkgs = ""
while (1) {
stop = (line ~ /;[ \t]*do([ \t]|$)/)
sub(/;[ \t]*do.*$/, "", line)
gsub(/\\/, "", line)
listpkgs = listpkgs " " line
if (stop) break
if ((getline line) <= 0) break
}
pending = listpkgs
next
}
/^[ \t]*(pacman_install|aur_install)[ \t]/ {
cmd = ($0 ~ /pacman_install/) ? "official" : "aur"
arg = $2
gsub(/["'\'']/, "", arg)
if (arg ~ /^\$/) {
# loop plumbing — emit the pending for-list under this source
n = split(pending, w, /[ \t]+/)
for (i = 1; i <= n; i++) if (w[i] != "") print cmd, w[i]
pending = ""
} else if (arg != "") {
print cmd, arg
}
}
' "$script" | sort -u
}
pairs=$(extract)
official=$(echo "$pairs" | awk '$1 == "official" { print $2 }')
aur=$(echo "$pairs" | awk '$1 == "aur" { print $2 }')
if [ "$mode" = list ]; then
echo "OFFICIAL ($(echo "$official" | grep -c .)):"
echo "$official" | sed 's/^/ /'
echo "AUR ($(echo "$aur" | grep -c .)):"
echo "$aur" | sed 's/^/ /'
exit 0
fi
# One batched AUR RPC query answers existence for every AUR-relevant name.
aur_query() {
# args: package names; prints the names the AUR knows
local args="" p
for p in "$@"; do args="$args&arg[]=$p"; done
"$CURL" -sm 20 "https://aur.archlinux.org/rpc/v5/info?${args#&}" 2>/dev/null \
| tr ',' '\n' | sed -n 's/.*"Name":[[:space:]]*"\([^"]*\)".*/\1/p'
}
# shellcheck disable=SC2086
aur_known=$(aur_query $official $aur)
in_repos() { "$PACMAN" -Si "$1" >/dev/null 2>&1; }
in_aur() { echo "$aur_known" | grep -qx "$1"; }
moved_to_aur="" now_official="" missing=""
for p in $official; do
in_repos "$p" && continue
if in_aur "$p"; then moved_to_aur="$moved_to_aur $p"; else missing="$missing $p"; fi
done
for p in $aur; do
if in_aur "$p"; then
in_repos "$p" && now_official="$now_official $p (also in repos)"
continue
fi
if in_repos "$p"; then now_official="$now_official $p"; else missing="$missing $p"; fi
done
rc=0
if [ -n "$missing" ]; then
echo "MISSING EVERYWHERE (not in repos, not in AUR):"
for p in $missing; do echo " $p"; done
rc=1
fi
if [ -n "$moved_to_aur" ]; then
echo "MOVED TO AUR (pacman_install will fail; switch to aur_install):"
for p in $moved_to_aur; do echo " $p"; done
rc=1
fi
if [ -n "$now_official" ]; then
echo "NOW IN OFFICIAL (aur_install works but pacman_install is cleaner):"
echo "$now_official" | tr ' ' '\n' | grep -v '^$' | sed 's/^/ /'
rc=1
fi
total=$(( $(echo "$official" | grep -c .) + $(echo "$aur" | grep -c .) ))
echo "---"
echo "$total packages audited"
exit $rc
|