#!/bin/bash
# aur-pkglist - print the AUR package list
[[ -v AUR_DEBUG ]] && set -o xtrace
argv0=pkglist
XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
AUR_LOCATION=${AUR_LOCATION:-'https://aur.archlinux.org'}
AUR_METADEST=${AUR_METADEST:-$XDG_CACHE_HOME/aurutils/$argv0} # variable name prone to change
PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'

# default options
ttl=300 pkglist=packages update=0 verify=0 use_system_time=0

http_last_modified() {
    awk -F', ' '/^[Ll]ast-[Mm]odified:/ {print $2}' "$1"
}

list_fetch() {
    curl -A aurutils -f "$1" "${@:2}" --remote-name
}

list_headers() {
    curl -A aurutils -f "$1" --head -Ss
}

usage() {
    printf >&2 'usage: %s [-bqsiv] [-t ttl] [-FP pattern]\n' "$argv0"
    exit 1
}

source /usr/share/makepkg/util/parseopts.sh

opt_short='t:bqsivFPJISu'
opt_long=('pkgbase' 'search' 'info' 'fixed-strings' 'perl-regexp' 'plain'
          'ttl:' 'users' 'verify' 'quiet' 'systime')
opt_hidden=('dump-options' 'time:' 'json')

if ! parseopts "$opt_short" "${opt_long[@]}" "${opt_hidden[@]}" -- "$@"; then
    usage
fi
set -- "${OPTRET[@]}"

unset mode
while true; do
    case "$1" in
        -b|--pkgbase)
            pkglist=pkgbase ;;
        -s|--search)
            pkglist=packages-meta-v1.json ;;
        -i|--info)
            pkglist=packages-meta-ext-v1.json ;;
        --users)
            pkglist=users ;;
        -F|--fixed-strings)
            mode=fixed ;;
        -P|--perl-regexp)
            mode=regex ;;
        --plain)
            mode=plain ;;
        -q|--quiet)
            mode=none ;;
        -t|--time|--ttl)
            shift; ttl=$1 ;;
        -v|--verify)
            verify=1 ;;
        --systime)
            use_system_time=1 ;;
        # Deprecated options
        -u) printf >&2 'deprecation notice: %s -u is an alias for --quiet\n' "$argv0"
            mode=none ;;
        -I) printf >&2 'deprecation notice: %s -I is an alias for --info\n' "$argv0"
            pkglist=packages-meta-ext-v1.json ;;
        -S) printf >&2 'deprecation notice: %s -S is an alias for --search\n' "$argv0"
            pkglist=packages-meta-v1.json ;;
        -J|--json)
            printf >&2 'deprecation notice: %s --json is an alias for --info | jq\n' "$argv0"
            mode=plain ;;
        --dump-options)
            printf -- '--%s\n' "${opt_long[@]}" ${AUR_DEBUG+"${opt_hidden[@]}"}
            printf -- '%s' "${opt_short}" | sed 's/.:\?/-&\n/g'
            exit ;;
        --) shift; break ;;
    esac
    shift
done

# default to regex if >0 arguments specified
if [[ ! -v mode ]] && (( $# > 0 )); then
    mode=regex
elif [[ ! -v mode ]]; then
    mode=plain
fi

if ! [[ $ttl =~ [0-9]+ ]]; then
    printf >&2 "error: --ttl requires an integer ('%s' provided)\n" "$ttl"
    exit 1
fi

# packages.gz cache
install -dm700 "$AUR_METADEST"
cd "$AUR_METADEST" || exit

if [[ ! -s headers_$pkglist || ! -s $pkglist ]]; then
    update=1

elif [[ -s $pkglist ]]; then
    sec_l=$(http_last_modified "headers_$pkglist" | date -f - '+%s')

    if (( use_system_time )); then
        sec_d=$(date '+%s')
    else
        sec_d=$(http_last_modified <(list_headers "$AUR_LOCATION/$pkglist.gz") | date -f - '+%s')
    fi

    if (( sec_d - sec_l > ttl )); then
        update=1
    fi
fi

if (( update )); then
    list_fetch "$AUR_LOCATION/$pkglist.gz" --dump-header "headers_$pkglist"

    if (( verify )); then
        list_fetch "$AUR_LOCATION/$pkglist.gz.sha256"
        sha256sum --check --strict --quiet "$pkglist.gz.sha256" || exit
    fi

    if [[ $pkglist == *.json ]]; then
        # Remove newlines separating partial objects, i.e.
        #   [\n{...},\n{...},...\n]  =>  [{...}{...},...]\n
        { gunzip -c "$pkglist.gz" | tr -d '\n'
          printf '\n'
        } > "$pkglist"
    else
        gunzip -f "$pkglist.gz"
    fi
fi >&2

# pattern match
case $mode in
    plain)
        cat "$pkglist" ;;
    fixed)
        grep -F "$1" "$pkglist" ;;
    regex)
        grep -P "$1" "$pkglist" ;;
    none)
        printf '%s\n' "$PWD/$pkglist" ;;
esac

# vim: set et sw=4 sts=4 ft=sh:
