#!/usr/bin/sh
# shellcheck disable=SC1090

# Rebuild the Freight cache from the Freight library.  The cache contains
# actual repositories that are suitable targets for `apt-get` (and maybe
# more in the future).

#/ Usage: freight cache [-k] [-g <email>] [-p <passphrase-file>] [-a <digest-algorithm>] [-c <conf>] [-v] [-h] [<manager>/<distro>][...]
#/   -k, --keep                          keep unreferenced versions of packages
#/   -g <email>, --gpg=<email>           GPG key to use, may be given multiple times
#/   -p <passphrase file>,
#/   --passphrase-file=<passphrase-file> path to file containing the passphrase of the GPG key
#/   -a <digest algorithm>,
#/   --digest-algo=<digest-algorithm>    digest algorithm that GPG should use, e.g SHA512
#/   -c <conf>, --conf=<conf>            config file to parse
#/   -v, --verbose                       verbose mode
#/   -h, --help                          show this help message

set -e

usage() {
    grep "^#/" "$0" | cut -c"4-" >&2
    exit "$1"
}
while [ "$#" -gt 0 ]; do
    case "$1" in
        -k | --keep) KEEP=1 shift ;;
        -g | --gpg)
            if [ -z "$GPG" ]; then
                GPG=$2
            else
                GPG="$GPG $2"
            fi
            shift 2
            ;;
        -g*)
            if [ -z "$GPG" ]; then
                GPG=$(echo "$1" | cut -c"3-")
            else
                GPG="$GPG $(echo "$1" | cut -c"3-")"
            fi
            shift
            ;;
        --gpg=*)
            if [ -z "$GPG" ]; then
                GPG=$(echo "$1" | cut -c"7-")
            else
                GPG="$GPG $(echo "$1" | cut -c"7-")"
            fi
            shift
            ;;
        -p | --passphrase-file) GPG_PASSPHRASE_FILE="$2" shift 2 ;;
        -p*) GPG_PASSPHRASE_FILE="$(echo "$1" | cut -c"3-")" shift ;;
        --passphrase-file=*) GPG_PASSPHRASE_FILE="$(echo "$1" | cut -c"19-")" shift ;;
        -a | --digest-algo) GPG_DIGEST_ALGO="$2" shift 2 ;;
        -a*) GPG_DIGEST_ALGO="$(echo "$1" | cut -c"3-")" shift ;;
        --digest-algo=*) GPG_DIGEST_ALGO="$(echo "$1" | cut -c"15-")" shift ;;
        -c | --conf) CONF="$2" shift 2 ;;
        -c*) CONF="$(echo "$1" | cut -c"3-")" shift ;;
        --conf=*) CONF="$(echo "$1" | cut -c"8-")" shift ;;
        -v | --verbose) VERBOSE=1 shift ;;
        -h | --help) usage 0 ;;
        -*)
            echo "# [freight] unknown switch: $1" >&2
            usage 1
            ;;
        *) break ;;
    esac
done

LIB="/usr/share/freight"
. "$LIB/conf.sh"

# If `GPG_PASSPHRASE_FILE` is set the specified file should exist and be
# readable by the user running Freight.
[ -z "$GPG_PASSPHRASE_FILE" ] || [ -r "$GPG_PASSPHRASE_FILE" ] || echo "# [freight] could not read passphrase file: $GPG_PASSPHRASE_FILE." >&2

# If `GPG_DIGEST_ALGO` is unset, force it to the freight default of SHA512
[ -z "$GPG_DIGEST_ALGO" ] && GPG_DIGEST_ALGO="SHA512"

# Create a working directory on the same device as the Freight cache.
mkdir -p "$VARCACHE"
TMP="$(mktemp -d "$VARCACHE/work.$$.XXXXXXXXXX")"
# shellcheck disable=SC2064
trap "rm -rf \"$TMP\"" EXIT INT TERM

# Enter the Freight library directory so that items in `$@` may be given as
# absolute paths or as partial paths of the form `<manager>/<distro>` that
# are ultimately taken relative to the Freight library.
mkdir -p "$VARLIB"
cd "$VARLIB"

# Rebuild each distro serially.
if [ -z "$*" ]; then
    DIRS="$(
        find "$VARLIB"/ -mindepth 2 -maxdepth 2 -type d -printf "%P\n" |
            grep -v '^\.' |
            tr "\n" " "
    )"
else
    DIRS=$*
fi
for DIR in $DIRS; do

    # Parse the manager and distro out of the Freight library path.
    DIR="$(readlink -f "$DIR")"
    DIR="${DIR##"$(readlink -f "$VARLIB")/"}"
    MANAGER="$(dirname "$DIR")"
    DIST="$(basename "$DIR")"

    # Should we follow symbolic links when finding components to cache?
    [ "$SYMLINKS" = "on" ] && FIND_L="-L" || FIND_L=""

    # From here the process is customized on a per-manager basis.  The
    # sorted list of package filenames comes on `stdin` and the name of
    # the distro is the only argument.  From there, each manager can do
    # whatever it wants.
    . "$LIB/$MANAGER.sh"
    SORT="$(sort -V <"/dev/null" 2>"/dev/null" && echo "sort -V" || echo "sort")"
    find $FIND_L "$DIR" -type "f" -printf "%P\n" 2>"/dev/null" |
        eval "$SORT" |
        eval "${MANAGER}_cache" "$DIST"

    # Clean up old packages as dictated by the manager.
    if [ -z "$KEEP" ]; then
        eval "${MANAGER}_clean"
    fi

done

# vim: et:ts=4:sw=4
