Skip to content

Commit 79c85cb

Browse files
add show-aur-changes script
The script identifies all AUR packages which have been modified within a given time. The script also supports the needed plumbing and convenience functionality such as fetching fresh metadata and git mirror updates, showing effective per-package diffs and cloning the mono repository from scratch. Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Christian Heusel <christian@heusel.eu>
1 parent 4c74fc5 commit 79c85cb

1 file changed

Lines changed: 122 additions & 0 deletions

File tree

aur/show-aur-changes

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/bash
2+
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
AUR_REPO_URL="https://github.com/archlinux/aur"
6+
7+
set -euo pipefail
8+
9+
usage() {
10+
cat <<EOF
11+
Usage: $(basename "$0") [-d|--diff] [-f|--fetch] [-n|--days <n>] [-m|--meta <path>] [-p|--pattern <glob>] [-r|--repo <path>] [--clone <path>]
12+
13+
Find AUR packages modified within a time window whose branches contain changes
14+
to files matching a given glob pattern.
15+
16+
Options:
17+
-d, --diff Print the effective diff for each matched package
18+
-f, --fetch Sync the local mirror and metadata to the latest state before running
19+
-n, --days <n> Look-back window in days (default: 7)
20+
-m, --meta <path> Path to packages-meta-v1.json (default: packages-meta-v1.json in the aur repo root)
21+
-p, --pattern <glob> File pattern to inspect (default: *)
22+
-r, --repo <path> Path to the AUR git checkout (default: git repo of current directory)
23+
--clone <path> Clone the AUR mono repository to <path> and use it as the repo
24+
-h, --help Show this help text
25+
EOF
26+
}
27+
28+
SHOW_DIFF=0
29+
FETCH=0
30+
DAYS=7
31+
META_JSON=""
32+
PATTERN="*"
33+
REPO_ROOT=""
34+
CLONE_PATH=""
35+
while [[ "${1:-}" == -* ]]; do
36+
case "$1" in
37+
-d|--diff) SHOW_DIFF=1 ;;
38+
-f|--fetch) FETCH=1 ;;
39+
-n|--days) shift; DAYS="$1" ;;
40+
-m|--meta) shift; META_JSON="$1" ;;
41+
-p|--pattern) shift; PATTERN="$1" ;;
42+
-r|--repo) shift; REPO_ROOT="$1" ;;
43+
--clone) shift; CLONE_PATH="$1" ;;
44+
-h|--help) usage; exit 0 ;;
45+
*) echo "Unknown flag: $1" >&2; echo >&2; usage >&2; exit 1 ;;
46+
esac
47+
shift
48+
done
49+
50+
if [[ -n "$CLONE_PATH" ]]; then
51+
echo "Cloning AUR mono repository to $CLONE_PATH ..." >&2
52+
git clone "$AUR_REPO_URL" "$CLONE_PATH"
53+
REPO_ROOT="$CLONE_PATH"
54+
fi
55+
56+
REPO_ROOT="${REPO_ROOT:-"$(git rev-parse --show-toplevel)"}"
57+
META_JSON="${META_JSON:-"$REPO_ROOT/packages-meta-v1.json"}"
58+
59+
if [[ ! -f "$META_JSON" ]] && ! (( FETCH )); then
60+
echo "error: metadata file not found: $META_JSON" >&2
61+
echo "hint: run with --fetch to download it" >&2
62+
exit 1
63+
fi
64+
65+
if (( FETCH )); then
66+
echo "Updating git mirror ..." >&2
67+
git -C "$REPO_ROOT" fetch --all --prune
68+
echo "Fetching latest metadata from aur.archlinux.org ..." >&2
69+
curl -fsSL "https://aur.archlinux.org/packages-meta-v1.json.gz" \
70+
| gzip -d > "$META_JSON"
71+
echo "Saved to $META_JSON" >&2
72+
fi
73+
74+
# Compute the cutoff as unix timestamp
75+
CUTOFF=$(date -d "-${DAYS} days" +%s)
76+
77+
# Collect the unique PackageBases modified since CUTOFF
78+
mapfile -t PKGS < <(
79+
jq -r --argjson cutoff "$CUTOFF" \
80+
'[.[] | select(.LastModified >= $cutoff)] | map(.PackageBase) | unique | .[]' \
81+
"$META_JSON"
82+
)
83+
84+
echo "Packages modified in the last ${DAYS} day(s): ${#PKGS[@]}" >&2
85+
echo "File pattern: $PATTERN" >&2
86+
87+
# For each package, check if its branch has matching file changes since $CUTOFF
88+
SINCE_DATE=$(date -d "-${DAYS} days" --iso-8601=seconds)
89+
90+
for pkg in "${PKGS[@]}"; do
91+
# Check if the remote branch exists
92+
if ! git -C "$REPO_ROOT" rev-parse --verify "origin/$pkg" &>/dev/null; then
93+
echo "error: no remote branch for package '$pkg'" >&2
94+
exit 1
95+
fi
96+
97+
# Check if there are any commits matching $PATTERN for this package since $CUTOFF
98+
if git -C "$REPO_ROOT" log "origin/$pkg" --since="$SINCE_DATE" --name-only --format="" -- "$PATTERN" | grep -q .; then
99+
echo "$pkg"
100+
101+
if (( SHOW_DIFF )); then
102+
# Find the boundary commits for the range touching $PATTERN
103+
mapfile -t commits < <(
104+
git -C "$REPO_ROOT" log "origin/$pkg" --since="$SINCE_DATE" --format="%H" -- "$PATTERN"
105+
)
106+
newest="${commits[0]}"
107+
oldest="${commits[-1]}"
108+
# Diff from the parent of the oldest in-range commit (empty tree if root)
109+
if git -C "$REPO_ROOT" rev-parse "${oldest}^" &>/dev/null; then
110+
base="${oldest}^"
111+
else
112+
# So far this always outputs the magic value
113+
# '4b825dc642cb6eb9a060e54bf8d69288fbee4904', but instead of hardcoding
114+
# it we regenerate it each time to not rely on it
115+
#
116+
# https://stackoverflow.com/a/9766506
117+
base="$(git mktree < /dev/null)"
118+
fi
119+
git -C "$REPO_ROOT" diff "$base" "$newest" -- "$PATTERN"
120+
fi
121+
fi
122+
done

0 commit comments

Comments
 (0)