Forked from
Core Modules / dune-common
2069 commits behind the upstream repository.
-
Christoph Grüninger authoredChristoph Grüninger authored
dune-git-whitespace-hook 5.37 KiB
#!/bin/sh
# dune-git-whitespace-hook
# DO NOT TOUCH THE PRECEDING LINE
# It is used by dunecontrol to enable automatic updates of the whitespace hook
# DUNE pre-commit hook to enforce whitespace policy
# This hook prevents adding lines with trailing whitespace and or tab characters
# in line indentation for certain files (see the TRAILING_WHITESPACE_DEFAULT and
# TAB_IN_INDENT_DEFAULT variables below for the default sets of files that will
# be checked).
# You can tell the hook which files should be inspected by setting the Git
# configuration variables "hooks.whitespace.trailing" and "hooks.whitespace.tabinindent".
# Those variables should contain valid Perl regular expressions. The names of modified
# files will be matched against those regexes.
# git-diff-index needs a valid commit to compare to
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
# By default, we disallow trailing whitespace for the following files, but the check for C/C++ and CMake sources
# happens in the tab-in-indent check to avoid confusing users with duplicate error messages
TRAILING_WHITESPACE_DEFAULT='^(dune\.module|README|README\.SVN|COPYING|INSTALL|TODO)$|^[^/]*(\.md|\.pc\.in)$|^doc/.*\.md$'
# By default, we disallow tabs in indents and trailing whitespace in C/C++ and CMake source files
TAB_IN_INDENT_DEFAULT='(^|/)CMakeLists\.txt$|(\.cpp|\.hpp|\.cc|\.hh|\.c|\.h|\.cmake|\.sh|\.py)$'
# Get user preferences
TRAILING_WHITESPACE_FILES=$(git config hooks.whitespace.trailing)
# Set default regex for disallowing trailing whitespace if the user did not set anything.
# We need to check the return value of git-config to distinguish the case
# when the user set an empty value
if [ $? -ne 0 ];
then
TRAILING_WHITESPACE_FILES="$TRAILING_WHITESPACE_DEFAULT"
fi
TAB_IN_INDENT_FILES=$(git config hooks.whitespace.tabinindent)
# Set default regex for disallowing tabs if the user did not set anything.
# We need to check the return value of git-config to distinguish the case
# when the user set an empty value
if [ $? -ne 0 ];
then
TAB_IN_INDENT_FILES="$TAB_IN_INDENT_DEFAULT"
fi
# Unfortunately, we have to mess directly with the repository config file,
# as git won't honor a custom config file specified by GIT_CONFIG
# backup repository-local user setting for core.whitespace
USER_WHITESPACE=$(git config --local --get core.whitespace)
if [ $? -ne 0 ];
then
USER_HAS_CUSTOM_WHITESPACE=0
else
USER_HAS_CUSTOM_WHITESPACE=1
fi
# Figure out how to call xargs to make sure it won't invoke its argument with
# an empty argument list. BSD xargs will not do that by default, while GNU xargs
# needs -r to do the same. So we start by checking whether xargs does the right
# thing without options. Now there could be other obscure versions of xargs out
# there (on clusters etc.) that behave in yet another way, so we try with -r as
# well. If that fails, we throw a big error message at the user.
# In the following line, xargs should not call false, so the return value should be 0.
echo "" | xargs false
if [ $? -ne 0 ]; then
# Let's try with -r
echo "" | xargs -r false
if [ $? -ne 0 ]; then
# Houston, we have a problem
if [ -z "$DUNE_WHITESPACE_IGNORE_XARGS" ]; then
echo "You seem to be lacking a version of xargs that is compatible to either BSD or GNU!" 1>&2
echo "Please file a bug report at http://dune-project.org about this issue with your exact operating system type and version!" 1>&2
echo "You can still use this hook by setting the environment variable DUNE_WHITESPACE_IGNORE_XARGS to 1, but please be aware" 1>&2
echo "that the hook might create false positives." 1>&2
echo "==============================================================" 1>&2
echo "Aborting the commit..." 1>&2
exit 99
else
SILENTXARGS=xargs
fi
else
SILENTXARGS="xargs -r"
fi
else
SILENTXARGS=xargs
fi
fail=0
done=0
do_cleanup()
{
if [ $done -ne 1 ];
then
echo "Error while executing whitespace checking pre-commit hook!" 1>&2
echo "There might still be whitespace errors in your commit!" 1>&2
fi
if [ $USER_HAS_CUSTOM_WHITESPACE -eq 1 ];
then
git config --replace-all core.whitespace "$USER_WHITESPACE"
else
git config --unset core.whitespace
fi
# be nice and let the commit go through if something went wrong along the
# way and we did not record a failure
exit $fail
}
trap do_cleanup EXIT
# set custom value
git config --replace-all core.whitespace trailing-space
if [ -z "$TRAILING_WHITESPACE_FILES" ];
then
git diff-index --check --cached $against --
result=$?
else
export TRAILING_WHITESPACE_FILES
git diff-index --cached --name-only $against \
| perl -ne 'print if /$ENV{TRAILING_WHITESPACE_FILES}/' \
| $SILENTXARGS git diff-index --check --cached $against --
result=$?
fi
if [ $result -ne 0 ];
then
fail=1
fi
git config --replace-all core.whitespace trailing-space,tab-in-indent
if [ -z "$TAB_IN_INDENT_FILES" ];
then
git diff-index --check --cached $against --
result=$?
else
export TAB_IN_INDENT_FILES
git diff-index --cached --name-only $against \
| perl -ne 'print if /$ENV{TAB_IN_INDENT_FILES}/' \
| $SILENTXARGS git diff-index --check --cached $against --
result=$?
fi
if [ $result -ne 0 ];
then
fail=1
fi
done=1
# trap will call the cleanup code