Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ BINDIR = $(PREFIX)/bin
BASH_SCRIPTS = \
admin/checkservices \
aur/review \
aur/show-aur-changes \
package/greposcope \
package/packages-signed-by \
package/parse-submodules \
Expand Down
113 changes: 73 additions & 40 deletions aur/show-aur-changes
Original file line number Diff line number Diff line change
Expand Up @@ -8,48 +8,64 @@ set -euo pipefail

usage() {
cat <<EOF
Usage: $(basename "$0") [-d|--diff] [-f|--fetch] [-n|--days <n>] [-m|--meta <path>] [-p|--pattern <glob>] [-r|--repo <path>] [--clone <path>]
Usage: $(basename "$0") [-d|--diff] [-f|--fetch] [-g|--grep <pattern>] [-n|--days <n>] [-m|--meta <path>] [-o|--output-dir <path>] [-p|--pattern <glob>] [-r|--repo <path>] [--clone <path>]

Find AUR packages modified within a time window whose branches contain changes
to files matching a given glob pattern.

Options:
-d, --diff Print the effective diff for each matched package
-f, --fetch Sync the local mirror and metadata to the latest state before running
-n, --days <n> Look-back window in days (default: 7)
-m, --meta <path> Path to packages-meta-v1.json (default: packages-meta-v1.json in the aur repo root)
-p, --pattern <glob> File pattern to inspect (default: *)
-r, --repo <path> Path to the AUR git checkout (default: git repo of current directory)
--clone <path> Clone the AUR mono repository to <path> and use it as the repo
-h, --help Show this help text
-d, --diff Print the effective diff for each matched package
-f, --fetch Sync the local mirror and metadata to the latest state before running
-g, --grep <pattern> Only include packages whose diff matches <pattern> (grep -E)
-n, --days <n> Look-back window in days (default: 7)
-m, --meta <path> Path to packages-meta-v1.json (default: packages-meta-v1.json in the aur repo root)
-o, --output-dir <path> Write each package's diff to <path>/<package>.patch
-p, --pattern <glob> File pattern to inspect (default: *)
-r, --repo <path> Path to the AUR git checkout (default: git repo of current directory)
--clone <path> Clone the AUR mono repository to <path> and use it as the repo
-h, --help Show this help text

Examples:
$(basename "$0") --repo ~/Documents/shared_projects/aur --fetch --diff --days 1
$(basename "$0") --repo ~/Documents/shared_projects/aur --output-dir ~/patches --days 1
$(basename "$0") --repo ~/Documents/shared_projects/aur --grep "npm install" --days 7
EOF
}

SHOW_DIFF=0
FETCH=0
GREP_PATTERN=""
DAYS=7
META_JSON=""
OUTPUT_DIR=""
PATTERN="*"
REPO_ROOT=""
CLONE_PATH=""
while [[ "${1:-}" == -* ]]; do
case "$1" in
-d|--diff) SHOW_DIFF=1 ;;
-f|--fetch) FETCH=1 ;;
-n|--days) shift; DAYS="$1" ;;
-m|--meta) shift; META_JSON="$1" ;;
-p|--pattern) shift; PATTERN="$1" ;;
-r|--repo) shift; REPO_ROOT="$1" ;;
--clone) shift; CLONE_PATH="$1" ;;
-h|--help) usage; exit 0 ;;
-d|--diff) SHOW_DIFF=1 ;;
-f|--fetch) FETCH=1 ;;
-g|--grep) shift; GREP_PATTERN="$1" ;;
-n|--days) shift; DAYS="$1" ;;
-m|--meta) shift; META_JSON="$1" ;;
-o|--output-dir) shift; OUTPUT_DIR="$1" ;;
-p|--pattern) shift; PATTERN="$1" ;;
-r|--repo) shift; REPO_ROOT="$1" ;;
--clone) shift; CLONE_PATH="$1" ;;
-h|--help) usage; exit 0 ;;
*) echo "Unknown flag: $1" >&2; echo >&2; usage >&2; exit 1 ;;
esac
shift
done

if [[ -n "$OUTPUT_DIR" ]]; then
if [[ -e "$OUTPUT_DIR" && ! -d "$OUTPUT_DIR" ]]; then
echo "error: output-dir '$OUTPUT_DIR' exists but is not a directory" >&2
exit 1
fi
mkdir -p "$OUTPUT_DIR"
fi

if [[ -n "$CLONE_PATH" ]]; then
echo "Cloning AUR mono repository to $CLONE_PATH ..." >&2
git clone "$AUR_REPO_URL" "$CLONE_PATH"
Expand Down Expand Up @@ -85,7 +101,8 @@ mapfile -t PKGS < <(
)

echo "Packages modified in the last ${DAYS} day(s): ${#PKGS[@]}" >&2
echo "File pattern: $PATTERN" >&2
echo "Limiting to files matching pattern: $PATTERN" >&2
[[ -n "$GREP_PATTERN" ]] && echo "Limiting to diffs matching pattern: $GREP_PATTERN" >&2

# For each package, check if its branch has matching file changes since $CUTOFF
SINCE_DATE=$(date -d "-${DAYS} days" --iso-8601=seconds)
Expand All @@ -98,28 +115,44 @@ for pkg in "${PKGS[@]}"; do
fi

# Check if there are any commits matching $PATTERN for this package since $CUTOFF
if git -C "$REPO_ROOT" log "origin/$pkg" --since="$SINCE_DATE" --name-only --format="" -- "$PATTERN" | grep -q .; then
echo "$pkg"

if (( SHOW_DIFF )); then
# Find the boundary commits for the range touching $PATTERN
mapfile -t commits < <(
git -C "$REPO_ROOT" log "origin/$pkg" --since="$SINCE_DATE" --format="%H" -- "$PATTERN"
)
newest="${commits[0]}"
oldest="${commits[-1]}"
# Diff from the parent of the oldest in-range commit (empty tree if root)
if git -C "$REPO_ROOT" rev-parse "${oldest}^" &>/dev/null; then
base="${oldest}^"
else
# So far this always outputs the magic value
# '4b825dc642cb6eb9a060e54bf8d69288fbee4904', but instead of hardcoding
# it we regenerate it each time to not rely on it
#
# https://stackoverflow.com/a/9766506
base="$(git mktree < /dev/null)"
fi
git -C "$REPO_ROOT" diff "$base" "$newest" -- "$PATTERN"
if ! git -C "$REPO_ROOT" log "origin/$pkg" --since="$SINCE_DATE" --name-only --format="" -- "$PATTERN" | grep -q .; then
continue
fi

diff_output=""
if (( SHOW_DIFF )) || [[ -n "$OUTPUT_DIR" ]] || [[ -n "$GREP_PATTERN" ]]; then
# Find the boundary commits for the range touching $PATTERN
mapfile -t commits < <(
git -C "$REPO_ROOT" log "origin/$pkg" --since="$SINCE_DATE" --format="%H" -- "$PATTERN"
)
newest="${commits[0]}"
oldest="${commits[-1]}"
# Diff from the parent of the oldest in-range commit (empty tree if root)
if git -C "$REPO_ROOT" rev-parse "${oldest}^" &>/dev/null; then
base="${oldest}^"
else
# So far this always outputs the magic value
# '4b825dc642cb6eb9a060e54bf8d69288fbee4904', but instead of hardcoding
# it we regenerate it each time to not rely on it
#
# https://stackoverflow.com/a/9766506
base="$(git -C "$REPO_ROOT" mktree < /dev/null)"
fi
diff_output=$(git -C "$REPO_ROOT" format-patch --no-binary --stdout "$base".."$newest" -- "$PATTERN")
fi

# Match against grep pattern if specified
if [[ -n "$GREP_PATTERN" ]] && ! grep -qE "$GREP_PATTERN" <<< "$diff_output"; then
continue
fi

echo "$pkg"

if (( SHOW_DIFF )) && [[ -n "$OUTPUT_DIR" ]]; then
printf '%s' "$diff_output" | tee "$OUTPUT_DIR/$pkg.patch"
elif (( SHOW_DIFF )); then
printf '%s' "$diff_output"
elif [[ -n "$OUTPUT_DIR" ]]; then
printf '%s' "$diff_output" > "$OUTPUT_DIR/$pkg.patch"
fi
done
Loading