#!/bin/sh
#
# Check if a gx program is installed and if its version is at least
# equal to a minimum version number.
#
# Call it for example like this:
#
#   $ check_gx_program "gx-go" "0.2.0" "Use 'make gx_upgrade' to install or upgrade gx-go."
#
# or:
#
#   $ check_gx_program "gx" "0.3" "Use 'make gx_upgrade' to install or upgrade gx."
#

USAGE="$0 GX_PROGRAM_NAME GX_MIN_VERSION UPGRADE_MSG"

die() {
    printf >&2 "fatal: %s\n" "$@"
    exit 1
}

# Get arguments

test "$#" -eq "3" || die "This program must be passed exactly 3 arguments" "Usage: $USAGE"

GX_PROGRAM_NAME="$1"
GX_MIN_VERSION="$2"
UPGRADE_MSG="$3"

die_upgrade() {
    printf >&2 "fatal: %s\n" "$@"
    printf >&2 "=> %s\n" "$UPGRADE_MSG"
    exit 1
}

major_number() {
    vers="$1"

    # Hack around 'expr' exiting with code 1 when it outputs 0
    case "$vers" in
        0) echo "0" ;;
        0.*) echo "0" ;;
        *) expr "$vers" : "\([^.]*\).*" || return 1
    esac
}

check_at_least_version() {
    MIN_VERS="$1"
    CUR_VERS="$2"
    PROG_NAME="$3"

    # Get major, minor and fix numbers for each version
    MIN_MAJ=$(major_number "$MIN_VERS") || die "No major version number in '$MIN_VERS' for '$PROG_NAME'"
    CUR_MAJ=$(major_number "$CUR_VERS") || die "No major version number in '$CUR_VERS' for '$PROG_NAME'"

    if MIN_MIN=$(expr "$MIN_VERS" : "[^.]*\.\([^.]*\).*"); then
        MIN_FIX=$(expr "$MIN_VERS" : "[^.]*\.[^.]*\.\([^.]*\).*") || MIN_FIX="0"
    else
        MIN_MIN="0"
        MIN_FIX="0"
    fi
    if CUR_MIN=$(expr "$CUR_VERS" : "[^.]*\.\([^.]*\).*"); then
        CUR_FIX=$(expr "$CUR_VERS" : "[^.]*\.[^.]*\.\([^.]*\).*") || CUR_FIX="0"
    else
        CUR_MIN="0"
        CUR_FIX="0"
    fi

    # Compare versions
    VERS_LEAST="$PROG_NAME version '$CUR_VERS' should be at least '$MIN_VERS'"
    test "$CUR_MAJ" -gt $(expr "$MIN_MAJ" - 1) || die_upgrade "$VERS_LEAST"
    test "$CUR_MAJ" -gt "$MIN_MAJ" || {
        test "$CUR_MIN" -gt $(expr "$MIN_MIN" - 1) || die_upgrade "$VERS_LEAST"
        test "$CUR_MIN" -gt "$MIN_MIN" || {
            test "$CUR_FIX" -ge "$MIN_FIX" || die_upgrade "$VERS_LEAST"
        }
    }
}

# Check that the gx program exists

type "$GX_PROGRAM_NAME" >/dev/null 2>&1 || die_upgrade "Program $GX_PROGRAM_NAME is not installed!"

# Check the gx program version

VERS_STR=$($GX_PROGRAM_NAME -v 2>&1) || die "'$GX_PROGRAM_NAME -v' failed with output: $VERS_STR"

GX_CUR_VERSION=$(expr "$VERS_STR" : ".*$GX_PROGRAM_NAME.* version \(.*\)") || die "Invalid '$GX_PROGRAM_NAME -v' output: $VERS_STR"

check_at_least_version "$GX_MIN_VERSION" "$GX_CUR_VERSION" "$GX_PROGRAM_NAME"
