Files @ a7f2a8344d3c
Branch filter:

Location: yaah/yaah

Dennis Fink
implemented -q and -v and updated yaah.rst
#!/bin/bash -

#:        Title: yaah - Yet another AUR helper
#:     Synopsis:
#:      Options:
#: Requirements: jshon <http://kmkeen.com/jshon/>
#:      Version: 0.1-alpha
#:      Created: 2013-02-26
#:     Revision: 2013-02-26
#:       Author: Dennis Fink <the_metalgamer@hackerspace.lu>

## Security
# Unalias everything
\unalias -a
# Secure PATH
PATH='/bin:/usr/bin'
export PATH
# Clearing the Command hash
hash -r
# Setting secure IFS
IFS=$' \t\n'
# Setting a secure umask
UMASK=002
umask $UMASK

## Script metadata
SCRIPTNAME=${0##*/}
DESCRIPTION="Yet another AUR helper"
DATE_OF_CREATION=2013-02-26
VERSION=0.1
AUTHOR="Dennis Fink <the_metalgamer@hackerspace.lu>"

readonly SCRIPTNAME DESCRIPTION DATE_OF_CREATION VERSION AUTHOR

## Constants
AURURL="http://aur.archlinux.org/"

readonly AURURL


## Set Colors (copied from makepkg)
if tput setaf 0 $>/dev/null; then
    ALL_OFF="$(tput sgr0)"
    BOLD="$(tput bold)"
    BLUE="${BOLD}$(tput setaf 4)"
    GREEN="${BOLD}$(tput setaf 2)"
    RED="${BOLD}$(tput setaf 1)"
    YELLOW="${BOLD}$(tput setaf 3)"
else
    ALL_OFF="\e[1;0m"
    BOLD="\[1;1m"
    BLUE="${BOLD}\e[1;34m"
    GREEN="${BOLD}\e[1;32m"
    RED="${BOLD}\e[1;31m"
    YELLOW="${BOLD}\e[1;33m"
fi

readonly ALL_OFF BOLD BLUE GREEN RED YELLOW


#=== FUNCTION =================================================================
#        Name: msg
# Description: Print message with a green pretag if $quiet is not set
# Parameter 1: Message to print
#==============================================================================

# copied from makepkg and modified
msg () {

    if [[ $quiet -eq 0 ]]; then
        local mesg=$1; shift
        printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@"
    fi
}

#=== FUNCTION =================================================================
#        Name: msg2
# Description: Print message with a blue pretag
# Parameter 1: Message to print
#==============================================================================

# copied from makepkg
msg2 () {

    local mesg=$1; shift
    printf "    ${BLUE}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@"

}

#=== FUNCTION =================================================================
#        Name: error
# Description: Print message with a red pretag an ERROR
# Parameter 1: Message to print
#==============================================================================

# copied from makepkg
error() {

    local mesg=$1; shift
    printf "${RED}==> ERROR:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2

}

#=== FUNCTION =================================================================
#        Name: check_version
# Description: Check version between to packages and print a message if the
#              later one is new
# Parameter 1: Name of the package
# Parameter 2: Version of the local package
# Parameter 3: Version of the online package
#==============================================================================

check_version () {

    if [[ $# -eq 3 ]]; then
        local name=$1
        local oldversion=$2
        local newversion=$3

        msg "Checking version for '$name'"

        if [[ $(vercmp $oldversion $newversion) -eq -1 ]]; then
            msg2 "New version for '$name': $oldversion -> $newversion"
        fi
    else
        error "Not enough parameters supplied"
        return 1
    fi

}

#=== FUNCTION =================================================================
#        Name: query_online_version
# Description: Querying online packages version
# Parameter 1: A bash array with the packagenames and version to check
#==============================================================================

query_online_version () {

    if [[ "$#" -eq 1 ]]; then

        msg "Getting version of online packages."

        declare -a packages=("${!1}")
        local arguments=""
        if [[ $verbose -ge 2 ]]; then
            msg "Creating argument list."
        fi
        for package in "${packages[@]}"; do
            arguments+="&arg\[\]=${package%\ *}"
        done

        if [[ $verbose -ge 1 ]]; then
            msg "Sending query to AUR."
        fi

        if [[ $verbose -ge 2 ]]; then
            msg "URL is: ${AURURL}rpc.php?type=multiinfo$arguments"
        fi

        local aur_response=$(curl -s -fL "${AURURL}rpc.php?type=multiinfo$arguments")

        if [[ $? -ne 0 ]]; then
            error "Packages infos could not be loaded!"
            return 1
        fi

        if [[ $verbose -ge 2 ]]; then
            msg "Getting numbers of objects in json array!"
        fi
        local number=$(jshon -Q -e results -l <<< "$aur_response")

        if [[ $verbose -ge 2 ]]; then
            msg "Looping over json array!"
        fi

        for i in $(seq 0 $(( $number -1 )) ); do

            if [[ $verbose -ge 2 ]]; then
                msg "Extracting package name."
            fi

            local package_name=${packages[$i]%\ *}

            if [[ $verbose -ge 2 ]]; then
                msg "Extracting old package version."
            fi

            local old_package_version=${packages[$i]#*\ }

            if [[ $verbose -ge 2 ]]; then
                msg "Extracting new package version."
            fi

            local new_package_version=$(jshon -Q -e results -e $i -e Version \
                <<< $aur_response | tr -d "\"")

            check_version $package_name $old_package_version $new_package_version
        done
    else
        error "Not enough parameters supplied"
        return 1
    fi

}

#=== FUNCTION =================================================================
#        Name: query_local_version
# Description: Querying local packages version
# Parameter *: Optional. The packages to query, if not specified, querying all
#              packages
#==============================================================================

query_local_version () {

    msg "Getting version of installed packages."

    local packages=()

    local IFS=$'\n'
    while read -r; do
        packages+=("$REPLY")
    done < <(pacman -Qm $@)
    if [[ $? -eq 0 ]]; then
        msg "There are ${#packages[@]} foreign packages to check."
        
        if [[ $verbose -ge 2 ]]; then
            msg "Sorting package array!"
        fi
        sorted_packages=($(sort <<<"${packages[*]}"))
        query_online_version sorted_packages[@]
    else
        error "Packages could not be loaded!"
        return 1
    fi

}

#=== FUNCTION =================================================================
#        Name: extract_and_remove
# Description: Extracting a tar.gz file and remove the archive file
# Parameter 1: File to extract
#==============================================================================

extract_and_remove () {

    if [[ $# -eq 1 ]]; then
        if [[ -f $1 ]]; then

            msg "Extracting '$1'"

            tar xzf $1 -C $downloaddir
            
            if [[ $verbose -ge 1 ]]; then
                msg "Removing '$1'"
            fi
            rm $1
        else
            error "'$1' is not a file"
            return 1
        fi
    else
        error "Not enough parameters supplied"
        return 1
    fi

}

#=== FUNCTION =================================================================
#        Name: download
# Description: Download a package from the AUR and extracting it
# Parameter 1: The package name to download
#==============================================================================

download () {

    if [[ $# -ne 0 ]]; then
        until [[ -z "$1" ]]; do
            local start=${1::2}
            local filename="${1}.tar.gz"

            msg "Downloading '$filename' to '$downloaddir'"

            curl -s -fL -o "$downloaddir/$filename" \
                "${AURURL}packages/$start/$1/$filename"

            if [[ $? -eq 0 ]]; then
                extract_and_remove "$downloaddir/$filename"
            else
                error "'$1' could not be found!"
                return 1
            fi
            shift
        done
    else
        error "Not enough parameters supplied!"
        return 1
    fi

}

#=== FUNCTION =================================================================
#        Name: usage
# Description: Prints the usage
#==============================================================================

usage() {
    printf "$SCRIPTNAME - $DESCRIPTION
    -h, --help Display help
    -c, --check Check installed packages if there are updates
    -d, --downloaddir <directory> Download packages to the specified directory\n"
}


check_flag=
verbose=0
quiet=0
downloaddir="$PWD"


while true; do
    case $1 in
        -h|--help|-\?)
            usage
            exit 0
            ;;
        -c|--check)
            check_flag=1
            shift
            ;;
        -d)
            downloaddir=$2
            shift 2
            ;;
        --downloaddir=*)
            downloaddir=${1#*=}
            shift
            ;;
        -v|--verbose)
            verbose=1
            shift
            ;;
        -vv)
            verbose=2
            shift
            ;;
        -q|--quiet)
            quiet=1
            shift
            ;;
        --)
            shift
            break
            ;;
        -*)
            error "Unknown option: $1"
            exit 1
            ;;
        *)
            break
            ;;
    esac
done

# check if downloaddir is a directory and remove trailing slash
if [[ -d $downloaddir ]]; then
    downloaddir=${downloaddir%/}
else
    error "$downloaddir is not a directory"
    exit 1
fi

if [[ "$check_flag" ]]; then
    query_local_version $@
else
    download $@
fi