graph: add REVERSE
[aurutils.git] / lib / aur-pkglist
blobea11f4aefcd3de48bf1dce76f93778c35d9bd69f
1 #!/bin/bash
2 # aur-pkglist - print the AUR package list
3 [[ -v AUR_DEBUG ]] && set -o xtrace
4 argv0=pkglist
5 XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
6 AUR_LOCATION=${AUR_LOCATION:-'https://aur.archlinux.org'}
7 AUR_METADEST=${AUR_METADEST:-$XDG_CACHE_HOME/aurutils/$argv0}
8 PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
10 # default options
11 ttl=300 pkglist=packages update=0 verify=0 use_system_time=0
13 args_csv() {
14 # shellcheck disable=SC2155
15 local str=$(printf '%s,' "$@")
16 printf '%s' "${str%,}"
19 http_last_modified() {
20 awk -F', ' '/^[Ll]ast-[Mm]odified:/ {print $2}' "$1"
23 list_fetch() {
24 curl -A aurutils -f "$1" "${@:2}" --remote-name
27 list_headers() {
28 curl -A aurutils -f "$1" --head -Ss
31 usage() {
32 printf >&2 'usage: %s [-bqsiv] [-t ttl] [-FP pattern]\n' "$argv0"
33 exit 1
36 opt_short='t:bqsivFPu'
37 opt_long=('pkgbase' 'search' 'info' 'fixed-strings' 'perl-regexp' 'plain'
38 'ttl:' 'users' 'verify' 'quiet' 'systime')
39 opt_hidden=('dump-options' 'time:')
41 if opts=$(getopt -o "$opt_short" -l "$(args_csv "${opt_long[@]}" "${opt_hidden[@]}")" -n "$argv0" -- "$@"); then
42 eval set -- "$opts"
43 else
44 usage
47 unset mode
48 while true; do
49 case "$1" in
50 -b|--pkgbase)
51 pkglist=pkgbase ;;
52 -s|--search)
53 pkglist=packages-meta-v1.json ;;
54 -i|--info)
55 pkglist=packages-meta-ext-v1.json ;;
56 --users)
57 pkglist=users ;;
58 -F|--fixed-strings)
59 mode=fixed ;;
60 -P|--perl-regexp)
61 mode=regex ;;
62 --plain)
63 mode=plain ;;
64 -q|--quiet)
65 mode=none ;;
66 -t|--time|--ttl)
67 shift; ttl=$1 ;;
68 -v|--verify)
69 verify=1 ;;
70 --systime)
71 use_system_time=1 ;;
72 # Deprecated options
73 -u) printf >&2 'deprecation notice: %s -u is an alias for --quiet\n' "$argv0"
74 mode=none ;;
75 --dump-options)
76 printf -- '--%s\n' "${opt_long[@]}" ${AUR_DEBUG+"${opt_hidden[@]}"}
77 printf -- '%s' "${opt_short}" | sed 's/.:\?/-&\n/g'
78 exit ;;
79 --) shift; break ;;
80 esac
81 shift
82 done
84 # default to regex if >0 arguments specified
85 if [[ ! -v mode ]] && (( $# > 0 )); then
86 mode=regex
87 elif [[ ! -v mode ]]; then
88 mode=plain
91 if ! [[ $ttl =~ [0-9]+ ]]; then
92 printf >&2 "%s: --ttl requires an integer ('%s' provided)\n" "$argv0" "$ttl"
93 exit 1
96 # packages.gz cache
97 mkdir -p -- "$AUR_METADEST"
99 if [[ ! -s $AUR_METADEST/headers_$pkglist || ! -s $AUR_METADEST/$pkglist ]]; then
100 update=1
102 elif [[ -s $AUR_METADEST/$pkglist ]]; then
103 sec_l=$(http_last_modified "$AUR_METADEST/headers_$pkglist" | date -f - '+%s')
105 if (( use_system_time )); then
106 sec_d=$(date '+%s')
107 else
108 sec_d=$(http_last_modified <(list_headers "$AUR_LOCATION/$pkglist.gz") | date -f - '+%s')
111 if (( sec_d - sec_l > ttl )); then
112 update=1
116 if (( update )); then
117 list_fetch "$AUR_LOCATION/$pkglist.gz" --dump-header "$AUR_METADEST/headers_$pkglist" -o "$AUR_METADEST/$pkglist.gz"
119 if (( verify )); then
120 list_fetch "$AUR_LOCATION/$pkglist.gz.sha256" -o "$AUR_METADEST/$pkglist.gz.sha256"
121 sha256sum --check --strict --quiet "$AUR_METADEST/$pkglist.gz.sha256" || exit
124 if [[ $pkglist == *.json ]]; then
125 # Remove newlines separating partial objects, i.e.
126 # [\n{...},\n{...},...\n] => [{...}{...},...]\n
127 { gunzip -c "$AUR_METADEST/$pkglist.gz" | tr -d '\n'
128 printf '\n'
129 } > "$AUR_METADEST/$pkglist"
130 else
131 gunzip -f "$AUR_METADEST/$pkglist.gz"
133 fi >&2
135 # pattern match
136 case $mode in
137 plain)
138 cat "$AUR_METADEST/$pkglist" ;;
139 fixed)
140 grep -F "$1" "$AUR_METADEST/$pkglist" ;;
141 regex)
142 grep -P "$1" "$AUR_METADEST/$pkglist" ;;
143 none)
144 printf '%s\n' "$AUR_METADEST/$pkglist" ;;
145 esac
147 # vim: set et sw=4 sts=4 ft=sh: