#!/usr/bin/env bash
#
# prtverify 
# Version 0.4.4 - 2014-11-23
# Juergen Daubert <jue at jue dot li>


COMMAND=$(basename "${0%.*}")
MODDIR="/usr/lib/$COMMAND"
WHITELIST="$(ls -1 --color=none "$MODDIR"/*.wl)"
LOGLEVEL=15


### Functions

perror() {
    echo "=====  Error: $1" >&2
    exit 1
}

usage() {
    echo "Usage: ${0##*/} [options] port ...
options:
 -l <loglevel>
 -m clean-repo
 -m missing-deps  -c path_to_collection1 [-c path_to_collection2 ...]
 -m file-conflict -c path_to_collection1 [-c path_to_collection2 ...]
See prtverify(1) for a detailed description of all options."
    exit 0
}

checkcollections() {
    local dir
    if [ "${#COLLECTIONS[@]}" = 0 ]; then
        perror "Need one or more collection. Use -c option to set."
    fi

    for dir in "${COLLECTIONS[@]}"; do
        if [ ! -d "$dir" ]; then
            perror "$dir is not a directory"
        fi
        if [ -z "$(ls "$dir"/*/Pkgfile 2>/dev/null)" ]; then
            perror "$dir is not a valid CRUX port collection"
        fi
    done
}

cleanup() {
    [ -f "$FPDB" ] && rm -f "$FPDB"
    exit 0
}

checkmode() {
    case "$1" in
        clean-repo)    MODE_CR=1 ;;
        file-conflict) MODE_FC=1 ;;
        missing-deps)  MODE_MD=1 ;;
        *)             usage     ;;
    esac
}

getoptions() {
    while [ "$1" ]; do
        case "$1" in
             -l) shift
                 LOGLEVEL="$1"
                 (( LOGLEVEL > 0 && LOGLEVEL < 16 )) || \
                 { echo "Invalid loglevel; using 15." >&2; LOGLEVEL=15; } ;;
             -m) shift
                 checkmode "$1" ;;
             -c) shift
                 COLLECTIONS+=("$1") ;;
             -*) usage ;;
              *) [ -d "$1" ] && PORTS+=("$1") || \
                 echo "===== $1 is not a directory, ignoring" >&2 ;;
        esac
        shift
    done
    [ ${#PORTS[@]} -gt 0 ] || perror "No ports to verify!"
}

findmodules() {
    MODULES=()
    local mod

    while read -r mod; do
        MODULES+=("-f" "$mod")
    done < \
    <( ls -1 "$MODDIR"/[023]*.awk 2>/dev/null; \
       [ "$MODE_CR" ] && ls -1 "$MODDIR"/1*.awk  2>/dev/null )
}

mkfootprintdb() {
    local dir
    FPDB=$(mktemp -p "${TMPDIR:-/tmp}" prtverify.XXXXXXXX)

    for dir in "${COLLECTIONS[@]}"; do
        ls -1 "$dir"/*/.footprint 2>/dev/null
    done | xargs gawk \
        -v FOOTPRINTDB="$FPDB" \
        -f "$MODDIR"/00_prtverify_lib.awk \
        -f "$MODDIR"/90_mk_footprint_db.awk
}

mkportslist() {
    DEPENDABLE=""
    local c
    while read -r c; do DEPENDABLE+=" $c"; done < \
    <(for dir in "${COLLECTIONS[@]}"; do
    ls -1 "$dir"/*/Pkgfile 2>/dev/null | sed 's,/Pkgfile,,; s,.*/,,'
      done | sort | uniq)
}

runtests() {
    local dir

    for dir in "$@"; do
        gawk \
            -v LOG_LEVEL="$LOGLEVEL" \
            -v FOOTPRINTDB="$FPDB" \
            -v WHITE_LIST="$WHITELIST" \
            -v DEP_PORTS="$DEPENDABLE" \
            "${MODULES[@]}" "$dir"
    done
}

main() {
    [ $# -ge 1 ] || usage
    getoptions "$@"

    if [ "$MODE_FC" ] || [ "$MODE_MD" ]; then
        checkcollections
        if [ "$MODE_FC" ]; then 
            mkfootprintdb
        fi
        if [ "$MODE_MD" ]; then 
            mkportslist
        fi
    fi

    findmodules
    runtests "${PORTS[@]}"
    cleanup
}

### Main

export LC_ALL=C
shopt -s nullglob
trap "cleanup" HUP INT QUIT TERM

main "$@"

# End of file
