#!/usr/bin/env bash # Author: Jack L. Frost # Licensed under the Internet Software Consortium (ISC) license. # See LICENSE for its text. _self="${0##*/}" cfg_workdir="$PWD" cfg_aur_url="https://aur.archlinux.org" cfg_curl_opts=( '--silent' '--location' ) err() { printf "$@" >&2; } _cat() { while read -r; do printf '%s\n' "$REPLY"; done } usage() { _cat <<- EOF Usage: $_self [flags] Flags: -h Show this message. -s Search for . -S Search only in the sync db. Implies -s. -A Search only in AUR. Implies -s. -d Get the package sources (default). Set twice to also get the dependencies. -n Don't update existing git repos. -u Print out all (and download if -d/-dd) outdated AUR packages. -U Set AUR url. -w Set the working directory. --nossl Set curl's --insecure flag. EOF } aur.search() { declare i aur_api_search_data aur_search_result_num version description aur_api_search_data=$( curl "${cfg_curl_opts[@]}" "${cfg_aur_api}&type=search&arg=${1}" ) aur_search_result_num=$( jshon -e resultcount -u <<< "$aur_api_search_data" ) # Exit if nothing was found (( aur_search_result_num )) || { return 1; } while { read -r name read -r version read -r description } do printf '%s %s\n %s\n' "aur/$name" "$version" "$description" done < <( jshon -C -e results -a -e Name -u -p -e Version -u -p -e Description -u <<< "$aur_api_search_data" ) } aur.info() { declare pkg_aur_info aur_query_result pkg_aur_info=$( curl "${cfg_curl_opts[@]}" "${cfg_aur_api}&type=info&arg=${1}" 2>/dev/null ) aur_query_result=$( jshon -e resultcount -u <<< "$pkg_aur_info" ) (( aur_query_result )) || { return 1; } printf '%s' "$pkg_aur_info" } aur.get_updates() { declare -a foreign_packages updated_pkgs declare aur_api_multireq aur_api_data aur_api_data_length n p u n_name n_version l_name l_version read -d '' -r -a foreign_packages < <( pacman -Qqm ) for p in "${foreign_packages[@]}"; do aur_api_multireq+="&arg\[\]=$p" done aur_api_data=$( curl "${cfg_curl_opts[@]}" "${cfg_aur_api}&type=info${aur_api_multireq}" ) aur_api_data_length=$( jshon -e results -l <<< "$aur_api_data" ) (( aur_api_data_length-- )) for (( n=0; n<=aur_api_data_length; n++ )); do read -r n_name < <( jshon -e results -e "$n" -e Name -u <<< "$aur_api_data") read -r n_version < <( jshon -e results -e "$n" -e Version -u <<< "$aur_api_data" ) read -r l_name l_version < <( pacman -Q "$n_name" ) if (( $(vercmp "$n_version" "$l_version") )); then updated_pkgs+=( "$n_name" ) printf '%s\n' "$n_name" fi done if ! (( ${#updated_pkgs[@]} )); then printf 'No updates found\n' return 0 fi if (( flag_get )); then for u in "${updated_pkgs[@]}"; do aur.get < <( aur.info "$u" ) done fi } aur.get() { declare i pkg_aur_info pkg_base depends makedepends dep_name aur_api_multireq dep_name aur_deps_api_data aur_deps_count aur_deps read -r pkg_aur_info read -r pkg_base < <( jshon -e results -a -e Name -u <<< "$pkg_aur_info" ) cd "$cfg_workdir" printf 'Working in %s\n' "${cfg_workdir}" if [[ -d "$pkg_base" ]]; then if ! (( flag_nopull )); then printf 'Updating %s\n' "$pkg_base" cd "$pkg_base" git pull || { err 'Fail!' return 21 } fi else printf 'Cloning %s\n' "$pkg_base" git clone "https://aur.archlinux.org/${pkg_base}.git" || { err 'Fail!' return 19 } fi if (( flag_get_deps )); then cd "${cfg_workdir}/${pkg_base}" read -d '' -r -a depends < <( jshon -Q -e results -a -e Depends -a -u <<< "$pkg_aur_info" jshon -Q -e results -a -e MakeDepends -a -u <<< "$pkg_aur_info" ) for i in "${depends[@]}"; do dep_name="${i/[<>=]*}" aur_api_multireq+="&arg\[\]=$dep_name" done aur_deps_api_data=$( curl "${cfg_curl_opts[@]}" "${cfg_aur_api}&type=info${aur_api_multireq}" ) aur_deps_count=$( jshon -e resultcount <<< "$aur_deps_api_data" ) if (( aur_deps_count )); then printf "Getting dependencies for %s\n" "${pkg_base}" aur_deps=( $( jshon -e results -a -e Name -u <<< "$aur_deps_api_data" ) ) for i in "${aur_deps[@]}"; do aur.get < <(aur.info "$i") _result="$?" if (( _result > 0 && result != 17 )); then return "$_result" fi done fi fi } abs.get() { git clone "https://gitlab.archlinux.org/archlinux/packaging/packages/$1.git" "$cfg_workdir/$1" } set_argv() { declare arg opt c declare -g argv while (( $# )); do unset -v arg opt c case "$1" in (--) argv+=( "$1" ); break;; (--*) IFS='=' read arg opt <<< "$1" argv+=( "$arg" ) [[ "$opt" ]] && { argv+=( "$opt" ) } ;; (-*) while read -n1 c do case "$c" in -|'') :;; *) argv+=( "-$c" );; esac done <<< "$1" ;; (*) argv+=( "$1" );; esac shift done } main() { if [[ -f "$HOME/.config/prm.rc.sh" ]]; then source "$HOME/.config/prm.rc.sh" fi while (( $# )); do case "$1" in (--) shift; break;; (-h) usage; return 0;; (-s) flag_search=1;; (-A) flag_search=1 flag_search_aur=1;; (-S) flag_search=1 flag_search_syncdb=1;; (-U) cfg_aur_url="$2" shift;; (-u) flag_update=1;; (-d) if (( flag_get )); then flag_get_deps=1 else flag_get=1 fi ;; (-w) cfg_workdir="$2" shift;; (-n) flag_nopull=1;; (--nossl) cfg_curl_opts+=( '--insecure' );; (-*) err "Unknown key: %s\n" "$1" usage return 1 ;; (*) break;; esac shift done (( flag_search_aur && flag_search_syncdb )) && { unset flag_search_aur flag_search_syncdb } cfg_aur_api="${cfg_aur_url}/rpc?v=5" if (( flag_search )); then action=search elif (( flag_update )); then action=update elif (( flag_get )); then action=get fi if [[ "$1" ]]; then package="$1" fi [[ "$action" ]] || { usage return 1 } [[ -d "$cfg_workdir" ]] || { mkdir -p "$cfg_workdir" || { err "Can't create workdir: %s\n" "$cfg_workdir" return 1 } } case "$action" in (get) [[ "$package" ]] || { usage return 1 } pkg_aur_info=$( aur.info "$package" ) if (( ! "$?" )); then repo='aur' else read -r repo < <( pacman -Sp --print-format '%r' "$package" ) [[ "$repo" ]] || { err "Can't find package %s\n" "$package" return 1 } fi printf "Found %s in %s\n" "$package" "$repo" case "$repo" in (aur) aur.get <<< "$pkg_aur_info";; (core|extra|community|multilib) abs.get "$package" "$repo";; (*) err "Repository %s not supported\n" "$repo" return 1;; esac ;; (search) [[ "$package" ]] || { usage return 1 } if (( flag_search_aur )); then aur.search "$package" || { err "No packages found\n" return 1 } elif (( flag_search_syncdb )); then pacman -Ss "$package" else aur.search "$package" || { flag_aur_search_fail=1; } pacman -Ss "$package" 2>/dev/null || { flag_pacman_search_fail=1; } if (( flag_aur_search_fail && flag_pacman_search_fail )); then err "No packages found\n" return 1 fi fi ;; (update) aur.get_updates ;; esac } set_argv "$@" main "${argv[@]}"