Skip to content

Instantly share code, notes, and snippets.

@ttys3
Forked from colinmollenhour/post-receive-redmine.sh
Last active March 22, 2020 06:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ttys3/479f23b86318e4e75e0a1059ff8b7e26 to your computer and use it in GitHub Desktop.
Save ttys3/479f23b86318e4e75e0a1059ff8b7e26 to your computer and use it in GitHub Desktop.
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
# from: https://gist.github.com/colinmollenhour/1248871/1df28b5e97c53a8032b575d9084b30a2e34e0be4
#
# 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)'
OVERRIDE_REGEX='Contains CRLF'
refname="$1"
oldrev="$2"
newrev="$3"
[ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ] && \
{ echo "Usage: $0 <ref> <oldrev> <newrev>" >&2; exit 1; }
# skip when commit mesage contains override
MESSAGE=$(git show -s --format=format:"%s" $newrev)
[[ $MESSAGE =~ $OVERRIDE_REGEX ]] && exit 0
ret=0
while read old_mode new_mode old_sha1 new_sha1 status name
do
# skip lines showing parent commit
test -z "$new_sha1" && continue
# skip deletions
[ "$new_sha1" = "0000000000000000000000000000000000000000" ] && continue
# don't do a CRLF check for binary files
[[ $tmp =~ $BINARY_REGEX ]] && continue
# check for CRLF
CR=$(printf "\r")
if git cat-file blob $new_sha1 | grep -Eq "$CR$"; then
echo "CRLF DETECTED: $name"
ret=1
fi
done < <(git diff-tree -r "$oldrev" "$newrev")
if [ "$ret" = "1" ]; then
echo "###################################################################################################"
echo "# One or more files contained CRLF (Windows) line endings which are not allowed."
echo "# Please change the line endings to LF before committing and before trying to push."
echo "# You will have to amend your existing commits to not contain CRLF."
echo "Use \"git config [--global] core.autocrlf false\" to disable CRLF conversion."
echo "###################################################################################################"
fi
exit $ret
#!/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