graph: add REVERSE
[aurutils.git] / lib / aur-vercmp
blobf9298c073e3f754251b14964faa787eec3d41445
1 #!/bin/bash
2 # aur-vercmp - check packages for AUR updates
3 [[ -v AUR_DEBUG ]] && set -o xtrace
4 set -o pipefail
5 argv0=vercmp
6 PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
8 # default options
9 format=check target=aur all=0 quiet=0
11 args_csv() {
12 # shellcheck disable=SC2155
13 local str=$(printf '%s,' "$@")
14 printf '%s' "${str%,}"
17 my_vercmp() {
18 if [[ $1 == "$2" ]]; then
19 printf '%d' 0 # common case
20 else
21 vercmp "$1" "$2"
25 cmp_equal_or_newer() {
26 local pkg v_cmp v_in op
28 while read -r pkg v_cmp v_in; do
29 case $v_cmp in
30 -) op=2 ;; # - on field 2
31 *) op=$(my_vercmp "$v_in" "$v_cmp") ;;
32 esac
34 case $op in
35 -1) plain >&2 '%s %s is newer than %s' "$pkg" "$v_cmp" "$v_in" >&2
36 printf '%s\n' "$pkg" ;;
37 0) printf '%s\n' "$pkg" ;;
38 1) msg2 >&2 '%s %s -> %s' "$pkg" "$v_cmp" "$v_in" ;;
39 2) msg2 >&2 '%s (none) -> %s' "$pkg" "$v_in" ;;
40 esac
41 done
44 cmp_checkupdates() {
45 local pkg v_cmp v_in op
47 while read -r pkg v_cmp v_in; do
48 case $v_in in
49 -) op=2 ;; # - on field 3
50 *) op=$(my_vercmp "$v_in" "$v_cmp") ;;
51 esac
53 (( ! all )) && (( op > -1 )) && continue;
54 (( quiet )) && { printf '%s\n' "$pkg"; continue; }
56 case $op in
57 -1) printf '%s %s -> %s\n' "$pkg" "$v_in" "$v_cmp" ;;
58 0) printf '%s %s = %s\n' "$pkg" "$v_in" "$v_cmp" ;;
59 1) printf '%s %s <- %s\n' "$pkg" "$v_in" "$v_cmp" ;;
60 2) printf '%s (none) -> %s\n' "$pkg" "$v_cmp" ;;
61 esac
62 done
65 parse_aur() {
66 aur query -t info - | aur format -f '%n\t%v\n'
69 trap_exit() {
70 if [[ ! -v AUR_DEBUG ]]; then
71 rm -rf -- "$tmp"
72 else
73 printf >&2 'AUR_DEBUG: %s: temporary files at %s\n' "$argv0" "$tmp"
77 usage() {
78 plain >&2 'usage: %s [-acq] [-p path]' "$argv0"
79 exit 1
82 source /usr/share/makepkg/util/message.sh
84 if [[ ! -v NO_COLOR ]] && [[ ! -v AUR_DEBUG ]]; then
85 [[ -t 2 ]] && colorize
88 opt_short='p:u:acq'
89 opt_long=('all' 'current' 'path:' 'quiet' 'upair:')
90 opt_hidden=('dump-options')
92 if opts=$(getopt -o "$opt_short" -l "$(args_csv "${opt_long[@]}" "${opt_hidden[@]}")" -n "$argv0" -- "$@"); then
93 eval set -- "$opts"
94 else
95 usage
98 unset aux repo upair
99 while true; do
100 case "$1" in
101 -a|--all)
102 all=1 ;;
103 -c|--current)
104 format=equal ;;
105 -q|--quiet)
106 quiet=1 ;;
107 -p|--path)
108 shift; aux=$1
109 target='file' ;;
110 -u|--upair)
111 shift; upair=$1 ;;
112 --dump-options)
113 printf -- '--%s\n' "${opt_long[@]}" ${AUR_DEBUG+"${opt_hidden[@]}"}
114 printf -- '%s' "${opt_short}" | sed 's/.:\?/-&\n/g'
115 exit ;;
116 --) shift; break ;;
117 esac
118 shift
119 done
121 # shellcheck disable=SC2174
122 mkdir -pm 0700 -- "${TMPDIR:-/tmp}/aurutils-$UID"
123 tmp=$(mktemp --tmpdir "aurutils-$UID/$argv0.XXXXXXXX") || exit
124 trap 'trap_exit' EXIT
126 # check for interactive terminal
127 if [[ -t 0 ]]; then
128 cat >&2 <<EOF
129 Warning: Input is read from the terminal. You either know what you
130 Warning: are doing, or you forgot to pipe data into $argv0.
131 Warning: Press CTRL-D to exit.
134 sort -k 1b,1 >"$tmp"
136 # set filters
137 case $format in
138 check) cmp() { cmp_checkupdates; }
139 upair=${upair-1} ;; # join unpaired of target
140 equal) cmp() { cmp_equal_or_newer; }
141 upair=${upair-2} ;; # join unpaired of input
142 esac
144 # pipeline
145 case $target in
146 aur) awk '{print $1}' "$tmp" | parse_aur ;;
147 file) awk '{print $0}' "$aux" ;;
148 esac | sort -k 1b,1 | join -a "$upair" -e - -o 0,1.2,2.2 - "$tmp" | cmp
150 # vim: set et sw=4 sts=4 ft=sh: