#!/usr/bin/env bash
#**************************************************************************
#*                                                                        *
#*                                 OCaml                                  *
#*                                                                        *
#*                 David Allsopp, OCaml Labs, Cambridge.                  *
#*                                                                        *
#*   Copyright 2021 David Allsopp Ltd.                                    *
#*                                                                        *
#*   All rights reserved.  This file is distributed under the terms of    *
#*   the GNU Lesser General Public License version 2.1, with the          *
#*   special exception on linking described in the file LICENSE.          *
#*                                                                        *
#**************************************************************************

# Hygiene Checks: ensure that configure.ac generates configure
# This tests both branches and PRs. Any commit which updates either files which
# affect configure (configure.ac, VERSION, aclocal.m4 and build-aux/*) and also
# which alter this script.
# The behaviour is slightly different for pushes vs pull requests: in a PR, all
# commits must be correct; in a push, it must be the case that the configure is
# correct at the tip of the branch. This allows you to push a correcting PR to
# trunk, for example, but rejects a PR which includes bad commits (for increased
# bisect safety).

set -e

WANT=$(sed -ne 's/^AC_PREREQ(\[\(.*\)\])/\1/p' configure.ac)
HAVE=$(sh ./configure -V | sed -ne '/generated by GNU Autoconf/s/.* \+//p')
if [[ $WANT != "$HAVE" ]]; then
  echo -ne '\e[31mWrong Autoconf version: \e[0m '
  echo -e 'Have: \e[31m'"$HAVE"'\e[0m  Want: \e[32m'"$WANT"'\e[0m'
  echo "Run tools/autogen autoconf[-]$WANT"
  exit 1
fi

if [[ $2 = 'pull_request' ]]; then
  ALL_COMMITS_MUST_PASS=1
else
  ALL_COMMITS_MUST_PASS=0
fi

# We need all the commits in the PR to be available
. tools/ci/actions/deepen-fetch.sh

# Display failing commits in red for PRs and yellow for branches (error/warning)
if ((ALL_COMMITS_MUST_PASS)); then
  COLOR='31'
else
  COLOR='33'
fi

# $1 - commit to checkout files from
CheckTree () {
  local RET=0
  COMMIT="$1"
  git branch -qf 'return'
  git checkout -q "$COMMIT"
  mv configure configure.ref
  tools/autogen
  if diff -q configure configure.ref >/dev/null ; then
    echo -e "$COMMIT: \e[32mconfigure.ac generates configure\e[0m"
  else
    RET=1
    echo -e \
      "$COMMIT: \e[${COLOR}mconfigure.ac doesn't generate configure\e[0m"
  fi
  mv configure.ref configure
  git checkout -q 'return'
  return $RET
}

PATHS=(tools/ci/actions/check-configure.sh configure configure.ac VERSION \
       aclocal.m4 build-aux tools/autogen tools/git-dev-options.sh)

# $RESULT is 1 for success and 0 for error
RESULT=1
# We traverse the commits in commit order; if $ALL_COMMITS_MUST_PASS=0, the
# success of the most recent commit of the branch (traversed last) will
# override any previous failure.
for commit in $(git rev-list "$MERGE_BASE..$PR_HEAD" --reverse \
                      -- "${PATHS[@]}"); do
  if CheckTree "$commit"; then
    if ((!ALL_COMMITS_MUST_PASS)); then
      # Commit passed, so reset any previous failure
      RESULT=1
    fi
  else
    RESULT=0
  fi
done

if ((!RESULT)); then
  echo 'configure.ac no longer generates configure'
  if ((ALL_COMMITS_MUST_PASS)); then
    echo 'Please rebase the PR, editing the commits identified above and run:'
  else
    echo 'Please fix the branch by committing changes after running:'
  fi
  echo 'tools/autogen'
  exit 1
fi
