aurutils: v15
[aurutils.git] / lib / aur-view
blob38e6cd5201250f5a47421580920c41433e455f59
1 #!/bin/bash
2 # aur-view - inspect package files
3 [[ -v AUR_DEBUG ]] && set -o xtrace
4 set -o errexit
5 argv0=view
6 XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
7 AUR_VIEW_DB=${AUR_VIEW_DB:-$XDG_DATA_HOME/aurutils/$argv0}
8 PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
10 # default options
11 log_fmt='diff' log_args=() excludes=() patch=1 prefix=0
13 args_csv() {
14 # shellcheck disable=SC2155
15 local str=$(printf '%s,' "$@")
16 printf '%s' "${str%,}"
19 trap_exit() {
20 if [[ ! -v AUR_DEBUG ]]; then
21 rm -rf -- "$tmp"
22 else
23 printf >&2 'AUR_DEBUG: %s: temporary files at %s\n' "$argv0" "$tmp"
27 usage() {
28 plain >&2 'usage: %s [--format] <package...>' "$argv0"
29 exit 1
32 opt_short='a:'
33 opt_long=('format:' 'arg-file:' 'revision:' 'no-patch' 'confirm' 'exclude:' 'prefix')
34 opt_hidden=('dump-options')
36 if opts=$(getopt -o "$opt_short" -l "$(args_csv "${opt_long[@]}" "${opt_hidden[@]}")" -n "$argv0" -- "$@"); then
37 eval set -- "$opts"
38 else
39 usage
42 unset queue revision prefix
43 while true; do
44 case "$1" in
45 -a|--arg-file)
46 shift; queue=$1 ;;
47 --format)
48 shift
49 case $1 in
50 diff|log)
51 log_fmt=$1 ;;
53 error '%s: invalid --format option: %s' "$argv0" "$1"
54 usage ;;
55 esac ;;
56 --confirm)
57 AUR_CONFIRM_PAGER=1 ;;
58 --no-patch)
59 patch=0 ;;
60 --prefix)
61 prefix=1 ;;
62 --revision)
63 shift; revision=$1 ;;
64 --exclude)
65 shift; excludes+=("$1") ;;
66 --dump-options)
67 printf -- '--%s\n' "${opt_long[@]}" ${AUR_DEBUG+"${opt_hidden[@]}"}
68 printf -- '%s' "${opt_short}" | sed 's/.:\?/-&\n/g'
69 exit ;;
70 --) shift; break ;;
71 esac
72 shift
73 done
75 if (( patch )); then
76 log_args+=(--patch)
79 # shellcheck disable=SC2174
80 mkdir -pm 0700 -- "${TMPDIR:-/tmp}/aurutils-$UID"
81 tmp=$(mktemp -d --tmpdir "aurutils-$UID/$argv0.XXXXXXX")
82 trap 'trap_exit' EXIT
84 # Directory for git checksums (revisions viewed by the user, #379)
85 mkdir -p -- "$AUR_VIEW_DB"
87 # Take input from a file instead of redirecting stdin (#871)
88 packages=()
89 if [[ -v queue ]]; then
90 exec {fd}< "$queue"
92 while read -ru "$fd"; do
93 [[ $REPLY ]] && packages+=("$REPLY")
94 done
95 else
96 packages=("$@")
97 set --
100 if (( ! ${#packages[@]} )); then
101 printf >&2 "there is nothing to do"
102 exit
105 # Link build files in the queue (absolute links)
106 for pkg in "${packages[@]}"; do
107 [[ $pkg ]] && printf '%s\0' "$(pwd -P)/$pkg"
108 done | xargs -0 ln -t "$tmp" -s --
110 # Retrieve last viewed revisions
111 declare -A heads
113 for pkg in "${packages[@]}"; do
114 git() { command git -C "$pkg" "$@"; }
116 # Ensure every directory is a git repository (--continue)
117 if head=$(git rev-parse "${revision:-HEAD}"); then
118 heads[$pkg]=$head
119 else
120 printf >&2 '%s: %s: revision %s not found\n' "$argv0" "$pkg" "${revision:-HEAD}"
121 exit 2
124 unset path_args
125 if (( prefix )); then
126 path_args=(--src-prefix="$pkg/" --dst-prefix="$pkg/")
129 if [[ -f $AUR_VIEW_DB/$pkg ]] && read -r view < "$AUR_VIEW_DB/$pkg"; then
130 # Check if hash points to an existing object
131 if ! git cat-file -e "$view"; then
132 printf >&2 '%s: %s: invalid git revision\n' "$argv0" "$AUR_VIEW_DB/$pkg"
133 exit 22
136 if [[ $view != "$head" ]]; then
137 git --no-pager "$log_fmt" --stat "${log_args[@]}" "${path_args[@]}" \
138 "$view..$head" -- "${excludes[@]}" > "$tmp/$pkg.$log_fmt"
141 elif [[ -f $AUR_VIEW_DB/$pkg ]]; then
142 printf >&2 '%s: %s: failed to read revision\n' "$argv0" "$pkg"
143 exit 1
145 done
146 unset -f git
148 # Begin file inspection
149 if [[ -v AUR_PAGER ]]; then
150 # shellcheck disable=SC2086
151 command -- $AUR_PAGER "$tmp"
153 # Use an additional prompt for file managers with no support
154 # for exit codes greater 0 (#673)
155 if [[ -v AUR_CONFIRM_PAGER ]] && (( AUR_CONFIRM_PAGER )); then
156 read -rp $'Press Return to continue or Ctrl+d to abort\n'
159 elif type -P vifm >/dev/null; then
160 # Show hidden directories (.git)
161 shopt -s dotglob
163 { # Print patch files
164 for f in "$tmp"/*; do
165 [[ -f $f ]] && printf '%s\0' "$f"
166 done
168 # Print build directories (non-empty) in dependency order
169 for d in "$tmp"/*/; do
170 printf '%s\0' "$d" "$d"/*
171 done
172 # Avoid directory prefix in printed paths (#452)
173 } | env -C "$tmp" vifm -c 'set vifminfo=' -c 'view!' -c '0' -
175 else
176 printf >&2 '%s: no viewer found, please install vifm or set AUR_PAGER\n' "$argv0"
177 exit 1
180 # Update gitsums (viewer exited successfully)
181 for pkg in "${packages[@]}"; do
182 printf '%s\n' "${heads[$pkg]}" > "$AUR_VIEW_DB/$pkg"
183 done