#!/usr/bin/bash
# Update various generated artifacts in rpm packages.
# This should be run in the directory containing the spec file.
# * Go vendor archive and config
# * COPR source file
shopt -s extglob


__has_spec_file() {
    test -n "$SPEC_FILE"
}

__is_vendor_enabled() {
    __has_spec_file && grep -q go-vendor-tools.toml "$SPEC_FILE"
}

# shellcheck disable=SC2046,SC2086
__find_sources() {
    if [ -n "$SOURCES_FILE" ] && [ -d "$(dirname $SOURCES_FILE)" ] && [ "$PWD" != "$(dirname $SOURCES_FILE)" ]; then
        DO_POP=1
        pushd "$(dirname $SOURCES_FILE)" > /dev/null || exit 98
    fi

    if __has_spec_file; then
        SPECTOOL_SOURCES="$(spectool --list-files --sources "$SPEC_FILE")"
        if [ $? -ne 0 ]; then
            echo "The spec file $SPEC_FILE couldn't be parsed"
            exit 96
        fi
        FILTERED_SOURCES="$(echo "$SPECTOOL_SOURCES" | sed -e '/^Source[0-9]*:[[:blank:]]*sources/d' -e 's/^Source[0-9]*:[[:blank:]]*//')"
        if [ -n "$FILTERED_SOURCES" ]; then
            FILENAMES=$(basename -a "$FILTERED_SOURCES")
        fi
    elif [ -d .git ] && which git &>/dev/null; then
        FILENAMES=$(git ls-files --exclude-standard | grep -v -e '^\.' -e sources)
    elif which find &>/dev/null; then
        FILENAMES=$(find . -path "./RPMS" -prune -o -path "./BUILD" -prune -o -path "./SRPMS" -prune -o -path "./.*" -prune -o \( ! \( -name '*.spec' -o -name '.*' -o -name sources \) -a -type f \) -printf ' %P')
    else
        echo "No way to search for relevant source files was found. Please install find (and git if this is a git repository directory) or add a .spec file to the directory."
        exit 97
    fi
    if [[ "$DO_POP" -eq 1 ]]; then
        popd > /dev/null || echo $FILENAMES
    fi
    echo $FILENAMES
}

_usage() {
    echo "Usage: $(basename "$0") [OPTION]... [<SPEC_FILE>]"
    echo "Update generated artifacts. If <SPEC_FILE> is specified the referenced sources and artifacts are processed"
    echo "  otherwise a source file is created or updated in the current directory or in the directory the source"
    echo "  file parameter points to."
    echo
    echo "Options:"
    echo "  -a Update archive"
    echo "  -l Update licenses"
    echo "  -s Update sources file"
    echo "  -t Path to a file to write the source hashes to. The checksums will be calculated for files and subdirectories in the directory containing this file. Implies -s"
    echo "  -u Ignore unlicensed mods. Implies -l"
    echo "  -h Print this message and exit"
    echo
    echo "If none of the update operations are specified, all of them will"
    echo "be performed unless the spec is not go-vendor-tools enabled,"
    echo "in which case only the sources file will be updated."
}

_parse_args() {
    while getopts ":alsuht:" flag; do
        case "$flag" in
            a)
                UPDATE_ARCHIVE=1
                ;;
            l)
                UPDATE_LICENSES=1
                ;;
            s)
                UPDATE_SOURCES=1
                ;;
            t)
                SOURCES_FILE="$OPTARG"
                ;;
            u)
                IGNORE_UNLICENSED_ARG=" --ignore-unlicensed-mods"
                ;;
            h)
           	    _usage
           	    exit
                ;;
            \?)
                echo "Option -$OPTARG is invalid"
           	    echo
           	    _usage
           	    exit 9
                ;;
        esac
    done

    # Validate required positional .spec file value
    SPEC_FILE="${@:$OPTIND:1}"
    if __has_spec_file; then
        if ! [[ "$SPEC_FILE" =~ .*.\.spec$ ]]; then
            echo "The spec file $SPEC_FILE doesn't have a .spec extension"
            echo
            _usage
            exit 2
        fi
        if [ ! -f "$SPEC_FILE" ]; then
            echo "The spec file $SPEC_FILE is not readable"
            echo
            _usage
            exit 3
        fi
    fi

    # Default UPDATE_ vars if no particular operation was requested
    if [ -z "$UPDATE_ARCHIVE" ] && [ -z "$UPDATE_LICENSES" ] && [ -z "$UPDATE_SOURCES" ]; then
        if __is_vendor_enabled; then
            UPDATE_ARCHIVE=1
            UPDATE_LICENSES=1
        fi
        UPDATE_SOURCES=1
    fi

    # Set implied vars
    if [ -n "$IGNORE_UNLICENSED_ARG" ] && [ -z "$UPDATE_LICENSES" ]; then
        if ! __is_vendor_enabled; then
            echo "$SPEC_FILE is not go-vendor-tools enabled"
            exit 4
        fi
        UPDATE_LICENSES=1
    fi

    if [ -n "$SOURCES_FILE" ] && [ -z "$UPDATE_SOURCES" ]; then
        UPDATE_SOURCES=1
    fi
}

_check_go_vendor_enabled() {
    # go2rpm creates a go-vendor-tools.toml file when using the vendor profile
    if [[ "$UPDATE_ARCHIVE" -eq 1 || "$UPDATE_LICENSES" -eq 1 ]] && ! __is_vendor_enabled; then
        echo The spec file is not go-vendor-tools enabled
        exit 14
    fi
}

_download_sources() {
    if __has_spec_file; then
        if ! spectool -g "$SPEC_FILE"; then
            echo The spec file $SPEC_FILE is not parsable
            exit 96
        fi
    fi
}

_update_archive() {
    if ! __has_spec_file; then
        echo ERROR: Variable SPEC_FILE is not set
        exit 97
    fi
    # Update the go vendors archive
    if [[ "$UPDATE_ARCHIVE" -eq 1 ]]; then
        echo Updating go vendor archive
        if ! go_vendor_archive create --config go-vendor-tools.toml --write-config "$SPEC_FILE"; then
            echo Archive update failed
            exit 15
        fi
    fi
}

_update_licenses() {
    # Update the go vendors license config if it has changed
    if [[ "$UPDATE_LICENSES" -eq 1 ]]; then
        echo Updating go vendor licenses
        # shellcheck disable=SC2086
        if ! go_vendor_license --config go-vendor-tools.toml --path "$SPEC_FILE" report --write-config --prompt --autofill auto --update-spec$IGNORE_UNLICENSED_ARG; then
            echo License update failed
            exit 16
        fi
    fi
}

_update_sources() {
    # Update the sources checksums
    if [[ "$UPDATE_SOURCES" -eq 1 ]]; then
        if [ -n "$SOURCES_FILE" ] && [ -d "$(dirname $SOURCES_FILE)" ]; then
            DO_POP=1
            pushd "$(dirname $SOURCES_FILE)" > /dev/null || exit 98
        fi
        # The spec file and rpm build directories are excluded
        echo Calculating checksums
        # shellcheck disable=SC2046
        SOURCES="$(__find_sources)"
        if [ -z "$SOURCES" ]; then
            echo No relevant sources found. Skipping checksumming.
            return 0
        fi
        if ! cksum -a sha512 $SOURCES > "${SOURCES_FILE:-sources}"; then
            echo Sources checksum calculation failed
            exit 17
        fi

        if [[ "$DO_POP" -eq 1 ]]; then
            popd > /dev/null || exit 98
        fi
    fi
}

main() {
    _parse_args "$@"
    _download_sources
    _check_go_vendor_enabled
    _update_archive
    _update_licenses
    _update_sources

    echo Done
}

# Check if the script is being run directly, not sourced
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  main "$@"
fi
