#!/usr/bin/env bash #************************************************************************** #* * #* OCaml * #* * #* David Allsopp, MetaStack Solutions Ltd. * #* * #* Copyright 2017 MetaStack Solutions 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. * #* * #************************************************************************** # Bump this on any changes. It's vital that HOOK_VERSION followed by equals # appears nowhere else in these sources! HOOK_VERSION=6 # For what it's worth, allow for empty trees! if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # Redirect output to stderr. exec 1>&2 # Check to see if the script's been updated if git ls-files --error-unmatch tools/pre-commit-githook >/dev/null 2>&1 ; then THEIR_VERSION=$(git cat-file --textconv HEAD:tools/pre-commit-githook \ | sed -ne 's/^HOOK_VERSION=//p') if [[ -n $THEIR_VERSION && $THEIR_VERSION -gt $HOOK_VERSION ]] ; then echo "Note: tools/pre-commit-githook is newer than .git/hooks/pre-commit" echo " You may wish to update your local githook" fi fi # Git's built-in mechanism for whitespace is neater than ours, so do it first. # The strange construction below creates a list of files which have either # white-at-eol or white-at-eof included in ocaml-typo in .gitattributes and by # prefixing the names with :! causes git diff-index to skip over them. if [[ -n $(git diff-index --cached --name-only $against) ]] ; then FILES=$(git diff-index --cached --name-only $against \ | xargs git check-attr --cached ocaml-typo \ | sed -ne 's/\(.*\): ocaml-typo:.*[ ,]white-at-eo[fl]\(,\|$\)/:!\1/p') if ! git diff-index --check --cached $against -- $FILES ; then exit 1 fi else exit 0 fi # Test to see if any part of the directory name has been marked prune not_pruned () { DIR=$(dirname "$1") if [ "$DIR" = "." ] ; then return 0 else case ",$(git check-attr typo.prune "$DIR" | sed -e 's/.*: //')," in ,set,) return 1 ;; *) not_pruned "$DIR" return $? esac fi } # Now run check-typo over all the files in the index STATUS=0 export OCAML_CT_PREFIX=: export OCAML_CT_CAT="git cat-file --textconv" export OCAML_CT_CA_FLAG=--cached while IFS= read -r path do if not_pruned "$path" && ! tools/check-typo "./$path" ; then STATUS=1 fi done < <(git diff --diff-filter=d --staged --name-only) # If any files affecting the generation of configure have been updated, test # whether the index includes an up-to-date configure script. # See also tools/ci/actions/check-configure.sh AUTOCONF_FILES=\ 'configure configure.ac aclocal.m4 build-aux/* '\ 'tools/autogen tools/git-dev-options.sh' # Convert $AUTOCONF_FILES to a BRE PATHS="${AUTOCONF_FILES//./\\.}" PATHS="${PATHS//\*/.*}" PATHS="${PATHS// /\\|}" OVERRIDE_MESSAGE='(you can override githooks with git-commit --no-verify)' WRONG_AUTOCONF=0 if git diff --diff-filter=d --staged --name-only | grep -qx "$PATHS" ; then # Get the AC_PREREQ line in configure.ac for the required autoconf version PREREQ="$(git cat-file --textconv :configure.ac \ | sed -ne 's/^AC_PREREQ(\[\(.*\)\])/\1/p')" if [[ -z $PREREQ ]]; then echo 'Unable to find/parse the AC_PREREQ macro in configure.ac' echo 'This line should be of the form AC_PREREQ([2.69])' echo '(with no whitespace or comment)' STATUS=1 else # Check for autoconf and its version AUTOCONF_TOOL='autoconf' # Check version of autoconf set -o pipefail AUTOCONF_VERSION="$($AUTOCONF_TOOL --version 2>/dev/null | head -n 1)" if [[ $? -ne 0 ]]; then echo 'Files affecting configure updated, but autoconf not found' echo 'Unable to verify that configure is up-to-date' echo "$OVERRIDE_MESSAGE" STATUS=1 else AUTOCONF_VERSION="${AUTOCONF_VERSION##* }" if [[ $AUTOCONF_VERSION != $PREREQ ]]; then # Found autoconf, but it's the wrong version. If it's older, # tools/autogen will fail. If it's newer, it may succeed, but CI may # fail. autoconf is frequently available at an exact version, so try # the two known names for it. for tool in $AUTOCONF_TOOL-$PREREQ $AUTOCONF_TOOL$PREREQ; do VERSION="$($tool --version 2>/dev/null | head -n 1)" if [[ $? -eq 0 ]]; then VERSION="${VERSION##* }" if [[ $VERSION != $PREREQ ]]; then continue fi else continue fi echo "autoconf has version $AUTOCONF_VERSION; using $tool instead" AUTOCONF_TOOL="$tool" AUTOCONF_VERSION="$VERSION" break done fi if [[ $AUTOCONF_VERSION != $PREREQ ]]; then # We're using the wrong version of autoconf: if all other tests succeed, # display a warning that CI may complain (CI uses the version specified # by AC_PREREQ). WRONG_AUTOCONF=1 fi # Checkout the relevant files from the index to a temporary directory to # test them. BUILD_DIR="$(mktemp -d)" BUILD_DIR="${BUILD_DIR%%/}/" if [[ -z $BUILD_DIR ]]; then echo 'Unable to create a temporary directory to test configure.ac' STATUS=1 else git checkout-index --prefix "$BUILD_DIR" -- $AUTOCONF_FILES pushd "$BUILD_DIR" > /dev/null mkdir -p a b mv configure a/ echo 'Regenerating configure...' if tools/autogen "$AUTOCONF_TOOL"; then mv configure b/ if diff a/configure b/configure > /dev/null; then if ((WRONG_AUTOCONF)); then echo '*** Warning! configure.ac generates the configure script' echo "*** However, this is using autoconf $AUTOCONF_VERSION" echo "*** configure.ac requires autoconf $PREREQ; the CI check on" echo '*** GitHub may fail.' fi else echo 'configure.ac does not appear to generate configure' echo 'Try running tools/autogen and stage the changes' echo "$OVERRIDE_MESSAGE" git diff --text --no-index a b STATUS=1 fi else echo 'tools/autogen failed' STATUS=1 fi popd > /dev/null rm -rf "$BUILD_DIR" fi fi fi fi exit $STATUS