#!/usr/bin/env bash
# the following strips any trailing whitespace from the commit as well
# as turn any tab characters into spaces for python and cython files
# and updates local files to match
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
# add null object to repository for is-binary
NULL_OBJECT=`git hash-object -w /dev/null`
# based on
# http://stackoverflow.com/questions/6119956/how-to-determine-if-git-handles-a-file-as-binary-or-as-text
BINARY_NUMSTAT="`printf '%s\t-\t' -`"
is-binary () {
diffstat="`git diff --numstat $NULL_OBJECT $1`"
case $diffstat in
"$BINARY_NUMSTAT"*)
return 0
;;
*)
return 1
;;
esac
}
# set IFS to newlines for the following for loops
OIFS=$IFS
IFS=$'\n'
# fixed the index first
for line in `git diff-index --cached $against | sed "s/\t/ /" | cut -f2,4,6 -d' '`
do
mode="${line:0:6}"
object="${line:7:40}"
path="${line:48}"
if [ "${mode:0:2}" != "10" ]; then
# not a regular file in this case, so skip it
new_object=$object
elif is-binary $object; then
# don't mess with binaries (such as png files)
new_object=$object
elif [ "${path: -6}" == ".patch" -o "${path: -5}" == ".diff" ]; then
# don't mess with diff or patch files
new_object=$object
else
lines=`git cat-file -p $object | sed 's+\s*++g' | GREP_OPTIONS= egrep -n '^..*$' | sed 's+:.*++' | tail -1`
if [ \
"${path: -3}" == ".py" -o \
"${path: -4}" == ".pyx" -o \
"${path: -4}" == ".pxd" -o \
"${path: -4}" == ".pxi" -o \
"${path: -4}" == ".rst" ]; then
tabs="-e s+\t+ +g"
else
tabs=""
fi
new_object=`git cat-file -p $object | sed -e 's+\s*$++' $tabs | head -n $lines | git hash-object -w --stdin`
fi
echo -e "$mode $new_object\t$path"
done |
git update-index --index-info
# now fix the local files
for line in `git diff-index $against | sed "s/\t/ /" | cut -f2,6 -d' '`
do
mode="${line:0:6}"
path="${line:7}"
object=`git hash-object $path`
if [ "${mode:0:2}" != "10" ]; then
# not a regular file in this case, so skip it
true
elif is-binary $object; then
# don't mess with binaries (such as png files)
true
elif [ "${path: -6}" == ".patch" -o "${path: -5}" == ".diff" ]; then
# don't mess with diff or patch files
true
else
if [ \
"${path: -3}" == ".py" -o \
"${path: -4}" == ".pyx" -o \
"${path: -4}" == ".pxd" -o \
"${path: -4}" == ".pxi" -o \
"${path: -4}" == ".rst" ]; then
tabs="-e s+\t+ +g"
else
tabs=""
fi
sed -i -e 's+\s*$++' $tabs $path
echo "$path: removed all trailing whitespace"
if [ -n "$tabs" ]; then
echo "$path: replaced all tab characters with 4 spaces"
fi
lines=`sed 's+\s*++g' $path | GREP_OPTIONS= egrep -n '^..*$' | sed 's+:.*++' | tail -1`
if [ $lines -ne `wc -l $path | cut -d' ' -f1` ]; then
head -n $lines $path > $path.new && mv $path.new $path
echo "$path: removed all empty trailing newlines"
fi
fi
done
IFS=$OIFS
if git diff --cached --quiet; then
git status
exit 1
fi