#!/usr/bin/env bash

set -e

declare here repo_root test_script
here="$(perl -e 'use File::Basename; use Cwd "abs_path"; print dirname(abs_path(@ARGV[0]));' -- "$0")"
repo_root="$here/.."
test_script="$here/test"
export GIT_DIR="$here/../.git"

declare -a watchlist
watchlist=(googler tests)
while [[ $1 == -* ]]; do
    case $1 in
        -h|--help)
            cat <<'EOF'
Usage: ci-test-wrapper [-h|--help] [--monitor PATH [PATH ...]]

googler(1) testing wrapper for CIs.

Options:
    -h, --help
        Print this help and exit.
    --watch PATH [PATH ...]
        Additional paths (relative to repository root) to watch. Only run tests
        when watched paths have been modified. By default only googler and
        tests/ are watched, but sometimes additional paths should be watched
        depending on circumstances, e.g., for Travis, .travis.yml should also
        be watched. Note that this option consumes all of the remaining command
        line arguments.
EOF
            exit 1
            ;;
        --watch)
            shift
            watchlist=( "${watchlist[@]}" "$@" )
            shift $#
            break
            ;;
        *)
            printf '\033[31mError: Unrecognized option %q.\033[0m\n' "$1" >&2
            exit 1
            ;;
    esac
    shift
done
(( $# > 0 )) && {
    printf '\033[31mError: Unrecognized arguments %s.\033[0m\n' "$*" >&2
    exit 1
}

# Abort if the CI_SKIP_TEST environment variable is detected.
if [[ -n $CI_SKIP_TEST ]]; then
    printf 'Detected $CI_SKIP_TEST. Skipping tests.' >&2
    exit
fi

# Diff HEAD against a base commit to see if the changes are worth
# testing. (This check is skipped entirely if the CI_FORCE_TEST environment
# variable is set and non-nil.)
#
# * For a regular branch, diff against HEAD^;
# * For a PR branch, diff against the merge base of HEAD and master.
#
# Currently we use $TRAVIS_PULL_REQUEST to determine whether we're building a
# PR branch. Other criteria may be added if we ever expand to other CIs.

if [[ -z $CI_FORCE_TEST ]]; then
    printf 'We are watching the following paths:\n' >&2
    printf '    - %s\n' "${watchlist[@]}" >&2
    printf '\n' >&2

    declare diff_commits diff
    if [[ -z ${TRAVIS_PULL_REQUEST+x} || $TRAVIS_PULL_REQUEST == false ]]; then
        diff_commits='HEAD^..HEAD'
    else
        diff_commits='master...HEAD'
    fi
    diff=$(git -C "$repo_root" diff "$diff_commits" -- "${watchlist[@]}")
    if [[ -z $diff ]]; then
        printf 'None of the watchlist items changed, skipping tests.\n' >&2
        printf 'You may set the $CI_FORCE_TEST environment variable to force testing.\n' >&2
        exit 0
    else
        printf 'Changes to watchlist item(s) detected. Will test.\n\n' >&2
    fi
else
    printf 'Detected $CI_FORCE_TEST. Skipping necessity checks.\n\n' >&2
fi

# Test googler(1) with $repo_root at the beginning of $PATH (so that googler
# from this repo is picked up).
PATH="$repo_root:$PATH" "$test_script" --ci
