Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
gitolite update hooks to reject CRLF line endings and require formatted commit messages
#!/bin/bash
#
# see https://github.com/kahseng/redmine_gitolite_hook/blob/master/README.rdoc
#
# The "post-receive" script is run after receive-pack has accepted a pack
# and the repository has been updated. It is passed arguments in through
# stdin in the form
# <oldrev> <newrev> <refname>
# For example:
# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
REDMINE_SERVER=https://www.example.com/redmine
FETCH_URL=sys/fetch_changesets
APIKEY=YOUR_REDMINE_WS_API_KEY
# Project identifier defaults to repo name, but can be mapped
PROJECT="$GL_REPO"
MAP=( "foo:foo2"
"bar:baz" )
# Above can be overridden in ~/.redmine file
if [ -f ~/.redmine ]; then
. ~/.redmine
fi
for repomap in ${MAP[@]}; do
REPO=${repomap%%:*}
_PROJECT=${repomap#*:}
if [ "$GL_REPO" = "$REPO" ]; then
PROJECT="$_PROJECT"
break
fi
done
echo "Updating redmine project for $GL_REPO: $PROJECT"
lockfile=/tmp/redmine-update-${PROJECT//\//-}
if [ -f $lockfile ]; then
echo "$PROJECT is already being updated.."
echo "$PROJECT is already being updated.." >> /tmp/redmine-update.log
exit
fi
update_redmine() {
touch $lockfile
curl -k -s "$REDMINE_SERVER/$FETCH_URL?id=$PROJECT&key=$APIKEY" > /dev/null
rm $lockfile
echo $(date) Update $PROJECT completed >> /tmp/redmine-update.log
}
update_redmine &
disown -h
#!/bin/bash
$GL_BINDIR/hooks/update-reject-crlf $@ || exit 1
$GL_BINDIR/hooks/update-require-issue $@ || exit 1
exit 0
#!/bin/bash
#
# An "update" hook which rejects any update containing CRLF.
#
# Author: Gerhard Gappmeier, ascolab GmbH
# Author: Colin Mollenhour
#
# This script is based on the update.sample in git/contrib/hooks.
# You are free to use this script for whatever you want.
#
BINARY_REGEX='\.(pdb|dll|exe|png|gif|jpg|mwb|zip|tgz|gz|bz2|7z|rar|swf|fla|jar|mo|ttf|foo|mp3|icc|pdf|bmp|wmf|otf|eot|woff|phar|ico)$'
NO_EXTENSION_REGEX='/\w+$'
OVERRIDE_REGEX='Contains CRLF'
refname="$1"
oldrev="$2"
newrev="$3"
BADREV="0000000000000000000000000000000000000000"
[ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ] && \
{ echo "Usage: $0 <ref> <oldrev> <newrev>" >&2; exit 1; }
# Skip checks on branch deletions
[ "$newrev" = "$BADREV" ] && exit 0
# Skip checks on tag pushes
[[ $refname =~ ^refs\/tags\/ ]] && exit 0
FIRST=""
ERRORS=""
CR=$(printf "\r")
# Enable case-insensitive matching for file extensions
shopt -s nocasematch
for rev in $(git rev-list --reverse "$newrev" $(git for-each-ref --format='%(refname)' "refs/heads/*" | sed 's/^/\^/'))
do
# skip when commit mesage contains override
MESSAGE=$(git show -s --format=format:"%s" $rev)
[[ $MESSAGE =~ $OVERRIDE_REGEX ]] && continue
IS_BAD=0
while read old_mode new_mode old_sha1 new_sha1 status name
do
# skip lines showing parent commit and deletions
[[ -z "$new_sha1" ]] || [ "$new_sha1" = "$BADREV" ] && continue
# don't do a CRLF check for binary files
[[ $name =~ $BINARY_REGEX ]] && continue
# Skip pngs and executables without extensions
if [[ $name =~ $NO_EXTENSION_REGEX ]]; then
tmp=$(mktemp -t git-crlf.XXXXXXX)
git cat-file blob $new_sha1 > $tmp
<$tmp head -n 1 | grep -Fq "PNG" && { rm -f $tmp; continue; }
file $tmp | grep -Fq "executable" && { rm -f $tmp; continue; }
rm -f $tmp
fi
# check for CRLF
if git cat-file blob $new_sha1 | grep -Eq "$CR$"; then
if [ "$FIRST" = "" ]; then FIRST=$rev; fi
if [ $IS_BAD -eq 0 ]; then IS_BAD=1; ERRORS="${ERRORS}CRLF DETECTED IN ${rev:0:7}:\n"; fi
ERRORS="${ERRORS} $name\n"
fi
done < <(git diff-tree -r "$rev")
done
if [ "$FIRST" != "" ]; then
echo "###################################################################"
echo "# One or more files contained CRLF (Windows) line endings which are"
echo "# not allowed. Activate the autocrlf feature and/or change the line"
echo "# endings to LF before committing and before trying to push. You "
echo "# will have to amend your existing commits to not contain CRLF. "
echo "# \"git config core.autocrlf true\" to activate CRLF conversion."
echo "# \"git commit --amend\" to change your most recent commit."
echo "# \"git rebase -i ${FIRST:0:7}^\" to change all commits."
echo "###################################################################"
echo -e "$ERRORS"
exit 1
fi
#!/bin/bash
#
# An "update" hook which rejects any update with poor commit messages.
#
# Author: Colin Mollenhour
#
ISSUE_REGEX='\s*(refs|references|ticket|issue|feature|bug|task|fixes|closes|fixed) \#([0-9]+)[.:,]?\s*'
NO_ISSUE_REGEX='noref'
NO_ISSUE_GL_USER_REGEX='^(www-data)$'
NO_ISSUE_AUTHOR_EMAIL_REGEX='^(colin@.*mollenhour\.com|matt\.davenport@bss-llc\.com)$'
DEVELOP_MESSAGE_REGEX="into '?develop'?|develop'? into"
DEVELOP_REFNAME_REGEX='develop$'
MYSQL='mysql'
# Add authentication or put authentication in ~/.my.cnf
#MYSQL="$MYSQL -u redmine -pPASSWORD"
refname="$1"
oldrev="$2"
newrev="$3"
#echo "DEBUG - refname: $1, oldrev: $2, newrev: $3"
sep="---------------------------------------------"
function die { echo -e "$1" 1>&2; exit 1; }
[ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ] && \
die "Usage: $0 <ref> <oldrev> <newrev>"
[ -z "$GL_USER" ] && \
die "Gitolite user is not defined."
# Skip checks on branch deletions
[ "$newrev" = "0000000000000000000000000000000000000000" ] && exit 0
# Skip checks on tag pushes
[[ $refname =~ ^refs\/tags\/ ]] && exit 0
function reject {
die "
Your commit message was rejected for the following reason:
$1
$sep
$SHORT: $MESSAGE
$sep
HINT: Use 'git commit --amend' to modify your last commit or 'git rebase -i $SHORT^' to
modify all commits up to and including the offending one.
"
}
for REF in $(git rev-list --reverse "$newrev" $(git for-each-ref --format='%(refname)' "refs/heads/*" | sed 's/^/\^/')); do
SHORT=${REF:0:7}
MESSAGE=$(git show -s --format=format:"%s%+b" $REF | tr '\n' ' ')
AUTHOR_EMAIL=$(git show -s --format=format:"%ae" $REF)
shopt -s nocasematch
# Make sure the author email is populated
[ -z $AUTHOR_EMAIL ] && \
reject "You must configure your name and email address."
# Make sure that the log message contains some text.
[[ $MESSAGE =~ [a-zA-Z0-9]+ ]] || \
reject "You must supply a descriptive commit message."
# Allow an issue reference to be omitted if "noref" is added to message
if [[ $MESSAGE =~ $NO_ISSUE_REGEX ]]; then
[ -z $NO_ISSUE_GL_USER_REGEX ] && [ -z $NO_ISSUE_AUTHOR_EMAIL_REGEX ] && \
continue
[ -n $NO_ISSUE_GL_USER_REGEX ] && [[ $GL_USER =~ $NO_ISSUE_GL_USER_REGEX ]] && \
continue
[ -n $NO_ISSUE_AUTHOR_EMAIL_REGEX ] && [[ $AUTHOR_EMAIL =~ $NO_ISSUE_AUTHOR_EMAIL_REGEX ]] && \
continue
fi
# Reject merging develop into other branches
[[ $MESSAGE =~ $DEVELOP_MESSAGE_REGEX ]] && \
[[ ! $refname =~ $DEVELOP_REFNAME_REGEX ]] && \
reject "Develop branch may not be merged into other branches."
# Skip merge commits and commits that do nothing
NUMPARENTS=$(git cat-file -p $REF | grep '^parent ' | wc -l)
[ $NUMPARENTS -gt 1 -o "$(git diff --stat $REF $REF^)" == "" ] && \
continue
# Make sure that the log message references a Redmine issue.
[[ $MESSAGE =~ $ISSUE_REGEX ]] || \
reject "You must specify a Redmine issue number matching the following pattern:\n$ISSUE_REGEX\nExample: Issue #123, Refs #123, Fixes #123"
# Make sure the referenced issue actually exists
REDMINE_ISSUE=${BASH_REMATCH[2]}
REDMINE_ISSUE_EXISTS=$(${MYSQL} -N redmine -e "SELECT COUNT(*) FROM issues I WHERE I.id = ${REDMINE_ISSUE};")
[[ ${REDMINE_ISSUE_EXISTS} -ne 0 ]] || \
reject "Issue #${REDMINE_ISSUE} does not exist."
# Check message length, ignoring issue refs
MSGNOREF=${MESSAGE/${BASH_REMATCH[0]}}
[[ ${#MSGNOREF} -gt 10 ]] || \
reject "Your commit message \"$MSGNOREF\" is too short. Be more descriptive."
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.