83 lines
3.5 KiB
Bash
Executable file
83 lines
3.5 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
# This pre-receive hook is meant to be put in the main
|
|
# repository of the project to detect if a commit follow
|
|
# the rule for database updates.
|
|
# For example, with the issue #123, second script :
|
|
# - adding the file scripts/script_123-2.sql
|
|
# - putting the filename in the commit msg for easier retrieval
|
|
|
|
# When encountering non-UTF8 messages commit, sed may fail.
|
|
LANG=C
|
|
# Small attemp at making this script portable...
|
|
PATH_SCRUTINIZED="scripts"
|
|
|
|
# We fail on all uncaught errors
|
|
# and it helps us transmit error status outside
|
|
# of the loops
|
|
set -e
|
|
|
|
while read LINE; do
|
|
oldrev="$( echo $LINE | cut -f 1 -d ' ' )"
|
|
newrev="$( echo $LINE | cut -f 2 -d ' ' )"
|
|
refname="$( echo $LINE | cut -f 3 -d ' ' )"
|
|
|
|
# We ignore refs/tags and refs/remotes
|
|
if ! echo "$refname" | grep "^refs/heads/" >/dev/null; then
|
|
continue
|
|
fi
|
|
|
|
# In case oldrev is "000000..."
|
|
if [ "$oldrev" = "0000000000000000000000000000000000000000" ]; then
|
|
period="$newrev"
|
|
else
|
|
period="$oldrev..$newrev"
|
|
fi
|
|
|
|
# We loop over each commit to check if they
|
|
# put a script file to the scripts/ directory
|
|
# without having the following format in the
|
|
# first line of the commit message :
|
|
# [NNNN-NN-SQL] blabla... bla...
|
|
git log --pretty=oneline "$period" -- "$PATH_SCRUTINIZED" | while read COMMIT; do
|
|
# Commit metadata extraction
|
|
commitsha="$( echo "$COMMIT" | sed 's/^\([^ ]\+\) \(.*\)$/\1/' )"
|
|
commitmsg="$( echo "$COMMIT" | sed 's/^\([^ ]\+\) \(.*\)$/\2/' )"
|
|
|
|
# Listing of files modified by commit
|
|
# (git diff-tree will escape tab and other shell-risky characters, but not spaces)
|
|
IFS="$( printf "\t\n" )"
|
|
for filename in $( git diff-tree --no-commit-id --name-only --root -r "$commitsha" ); do
|
|
if echo "$filename" | grep "^$PATH_SCRUTINIZED/script"; then
|
|
# Check the filename is well-formed
|
|
if ! echo "$filename" | egrep "^$PATH_SCRUTINIZED/script_[0-9]{4,5}-[0-9]{2}.(sql|php)$" >/dev/null; then
|
|
echo "check-scripts: nom de fichier non conforme : $filename"
|
|
exit 1
|
|
fi
|
|
|
|
# Check the filename matches the commit message
|
|
mantis_number="$( echo "$filename" | sed -n 's#.*/script_\([0-9]\+\)-\([0-9]\+\).\(sql\|php\)#\1#p' )"
|
|
script_number="$( echo "$filename" | sed -n 's#.*/script_\([0-9]\+\)-\([0-9]\+\).\(sql\|php\)#\2#p' )"
|
|
extension="$( echo "$filename" | sed -n 's#.*/script_\([0-9]\+\)-\([0-9]\+\).\(sql\|php\)#\3#p' | tr "a-z" "A-Z" )"
|
|
if ! echo $commitmsg | grep "\[$mantis_number-$script_number-$extension\] " >/dev/null; then
|
|
echo "check-scripts: message de commit non conforme au script (filename : $filename) ($commitsha) : $commitmsg"
|
|
exit 1
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Inversely, for every commit message with the correct format, we
|
|
# check the matching file exists
|
|
if echo "$commitmsg" | egrep "^\[[0-9-]+[A-Z]{3}\]" >/dev/null; then
|
|
# Check the filename matches the commit message
|
|
mantis_number="$( echo "$commitmsg" | sed -n 's#^\[\([0-9]\{4,5\}\)-\([0-9]\{2\}\)-\(SQL\|PHP\)\] .*#\1#p' )"
|
|
script_number="$( echo "$commitmsg" | sed -n 's#^\[\([0-9]\{4,5\}\)-\([0-9]\{2\}\)-\(SQL\|PHP\)\] .*#\2#p' )"
|
|
extension="$( echo "$commitmsg" | sed -n 's#^\[\([0-9]\{4,5\}\)-\([0-9]\{2\}\)-\(SQL\|PHP\)\] .*#\3#p' | tr "A-Z" "a-z" )"
|
|
if [ -z "$mantis_number" ] || ! git diff-tree --no-commit-id --name-only --root -r "$commitsha" | grep "^$PATH_SCRUTINIZED/script_$mantis_number-$script_number.$extension$" >/dev/null; then
|
|
echo "check-scripts: aucun script SQL/PHP correspondant au message de commit ($commitsha) : $commitmsg"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
done
|
|
done
|