#!/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_aur_api="${cfg_aur_url}/rpc.php" echo() { printf '%s\n' "$*"; } err() { echo "$*" >&2; } usage() { while read; do echo "$REPLY"; done <<- 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. -f Force downloading package sources even if they are already present in the working directory. -w Set the working directory. Warning! Due to how the argument handling works, you can do this: $ zpac -wdd /tmp/workdir package Where /tmp/workdir is an argument to w. Don't do this. But it works, unfortunately. EOF } aur.search() { local aur_api_search_data aur_search_result_num pkg aur_api_search_data=$( curl -skL "${cfg_aur_api}?type=search&arg=${1}" ) aur_search_result_num=$( jshon -e resultcount -u <<< "$aur_api_search_data" ) if (( aur_search_result_num )); then aur_search_results=( $( jshon -e results -a -e Name -u <<< "$aur_api_search_data" ) ) for i in "${!aur_search_results[@]}"; do { read -r version read -r description } < <( jshon -e results -e $i -e Version -u -p -e Description -u <<< "$aur_api_search_data" ) printf '%s %s\n %s\n' "aur/${aur_search_results[$i]}" "$version" "$description" done else return 1 fi } aur.info() { local pkg_aur_info=$( curl -skL "${cfg_aur_api}?type=info&arg=${1}" 2>/dev/null ) local aur_query_result=$( jshon -e resultcount -u <<< "$pkg_aur_info" ) if (( aur_query_result )); then echo "$pkg_aur_info" else return 1 fi } aur.get() { local dep_name aur_api_multireq aur_deps_api_data aur_deps_count aur_deps pkg_aur_info pkg_base tarball_path read -r pkg_aur_info { read -r pkg_base read -r tarball_path } < <( jshon -e results -e PackageBase -u -p -e URLPath -u <<< "$pkg_aur_info" ) (( flag_force )) || { [[ -d "${cfg_workdir}/${pkg_base}" ]] && { echo "Found ${pkg_base} in ${cfg_workdir}, skipping. Use -f to override." return 17 } } cd "$cfg_workdir" echo "Working in ${cfg_workdir}" echo "Downloading ${pkg_base}" { curl -skL "${cfg_aur_url}${tarball_path}" | gzip -d | tar x; } || { err "Fail!" return 1 } if (( flag_get_deps )); then unset depends makedepends cd "${cfg_workdir}/${pkg_base}" source PKGBUILD for i in "${depends[@]}" "${makedepends[@]}"; do dep_name="${i/[<>=]*}" aur_api_multireq+="&arg\[\]=$dep_name" done aur_deps_api_data=$( curl -skL "${cfg_aur_api}?type=multiinfo${aur_api_multireq}" ) aur_deps_count=$( jshon -e resultcount <<< "$aur_deps_api_data" ) if (( aur_deps_count )); then echo "Getting dependencies for ${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="$?" (( _result )) && { (( _result == 17 )) || { return "$_result" } } done fi fi } abs.get() { local pkg_repo svn_repo pkg_repo="$2" case "$pkg_repo" in (community|multilib) svn_repo='community';; (*) svn_repo='packages';; esac svn checkout "svn://svn.archlinux.org/${svn_repo}/${1}/trunk" "${cfg_workdir}/${1}" } main() { if [[ -f "$HOME/.config/zpac.rc.sh" ]]; then source "$HOME/.config/zpac.rc.sh" fi while (( $# )); do case "$1" in (--) shift; break;; (-*) while read -n1 c do case "$c" in (-|'') :;; (h) usage; return 0;; (s) action='search';; (A) action='search' flag_search_aur=1;; (S) action='search' flag_search_syncdb=1;; (d) if [[ "$action" == 'get' ]]; then flag_get_deps=1 else action='get' fi ;; (w) cfg_workdir="$2" shift;; (f) flag_force=1;; (*) err "Unknown key: $1" usage return 1 ;; esac done <<< "$1" ;; (*) break;; esac shift done (( flag_search_aur && flag_search_syncdb )) && { unset flag_search_aur flag_search_syncdb } [[ "$action" ]] || { usage return 1 } if [[ "$1" ]]; then package="$1" else usage return 1 fi case "$action" in (get) [[ -d "$cfg_workdir" ]] || { mkdir -p "$cfg_workdir" || { err "Can't create workdir: ${cfg_workdir}." return 1 } } pkg_aur_info=$( aur.info "$package" ) if (( ! "$?" )); then repo='aur' else while read -r; do if [[ "$REPLY" =~ ^Repository ]]; then repo="${REPLY##* }" fi done < <( pacman -Si "$package" ) [[ "$repo" ]] || { err "Can't find package ${package}" return 1 } fi echo "Found ${package} in ${repo}." case "$repo" in (aur) aur.get <<< "$pkg_aur_info";; (core|extra|community|multilib) abs.get "$package" "$repo";; (*) err "Repository $repo not supported." return 1;; esac ;; (search) if (( flag_search_aur )); then aur.search "$package" || { err "No packages found." 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." return 1 fi fi ;; esac } main "$@"