Skip to content

Instantly share code, notes, and snippets.

@frimik
Created February 13, 2012 23:13
Show Gist options
  • Save frimik/1821358 to your computer and use it in GitHub Desktop.
Save frimik/1821358 to your computer and use it in GitHub Desktop.
git post-receive IRC notification
#!/bin/bash
#
# IRC notification post-receive hook.
# Based on https://wiki.icinga.org/display/community/GIT+Commit+Bot
#
# Author: Mikael Fridh <[email protected]>
#
# This script pulls out the commit information and sends it to
# the Notify plugin in supybot via localhost 5050.
#
# FIXME read host and port from git config
#
# Settings needed:
# git config hooks.irc.channel "#channel1 #channel2"
# git config hooks.irc.prefix "[repoprefix]"
#
# Optional settings:
# git config hooks.gitweb.baseurl "http://git.example.com/gitweb/?p="
# This option should contain everything prior to the repo name which will be
# appended.
#
# How I use it to do multiple notification hooks:
#
# in post-receive:
# FILE=$(mktemp)
# cat - > $FILE
#
# HOOKPATH=$(dirname $0)
#
# cat $FILE | ${HOOKPATH}/post-receive.email
# cat $FILE | ${HOOKPATH}/post-receive.irc
#
# rm $FILE
#
max=5
function notify ()
{
oldrev=$(git rev-parse $1)
newrev=$(git rev-parse $2)
refname="$3"
# --- Interpret
# 0000->1234 (create)
# 1234->2345 (update)
# 2345->0000 (delete)
if expr "$oldrev" : '0*$' >/dev/null
then
change_type="create"
else
if expr "$newrev" : '0*$' >/dev/null
then
change_type="delete"
else
change_type="update"
fi
fi
# --- Get the revision types
newrev_type=$(git cat-file -t $newrev 2> /dev/null)
oldrev_type=$(git cat-file -t "$oldrev" 2> /dev/null)
case "$change_type" in
create|update)
rev="$newrev"
rev_type="$newrev_type"
;;
delete)
rev="$oldrev"
rev_type="$oldrev_type"
;;
esac
# The revision type tells us what type the commit is, combined with
# the location of the ref we can decide between
# - working branch
# - tracking branch
# - unannoted tag
# - annotated tag
case "$refname","$rev_type" in
refs/tags/*,commit)
# un-annotated tag
refname_type="tag"
short_refname=${refname##refs/tags/}
;;
refs/tags/*,tag)
# annotated tag
refname_type="annotated tag"
short_refname=${refname##refs/tags/}
# change recipients
if [ -n "$announcerecipients" ]; then
recipients="$announcerecipients"
fi
;;
refs/heads/*,commit)
# branch
refname_type="branch"
short_refname=${refname##refs/heads/}
;;
refs/remotes/*,commit)
# tracking branch
refname_type="tracking branch"
short_refname=${refname##refs/remotes/}
echo >&2 "*** Push-update of tracking branch, $refname"
echo >&2 "*** - no notification generated."
return 0
;;
*)
# Anything else (is there anything else?)
echo >&2 "*** Unknown type of update to $refname ($rev_type)"
echo >&2 "*** - no notification generated"
return 0
;;
esac
channels=$(git config hooks.irc.channel)
# plural suffix, default "", changed to "s" if commits > 1
s=""
# Repo name, either Gitolite or normal repo.
if [ -n "$GL_REPO" ]; then
# it's a gitolite repo
repodir=$(basename `pwd`)
repo=$GL_REPO
else
repodir=$(basename `pwd`)
repo=${repodir%.git}
fi
gitweb_baseurl=$(git config hooks.gitweb.baseurl)
if [ -z "$gitweb_baseurl" ]; then
# if there is no value for gitweb_baseurl, fall back to some Marin
# default values
if [ -n "$GL_REPO" ]; then
# gitolite repo, add special gitolite/ prefix (Marin hardcoded until we
# move everything to gitolite hosting)
gitweb_baseurl="http://git.example.com/gitweb-beta/?p=gitolite/"
else
# non-gitolite repo, no special prefix
gitweb_baseurl="http://git.example.com/gitweb-beta/?p="
fi
fi
# otherwise, assume git config value is good:
url="${gitweb_baseurl}${repodir};a=commit;h="
head="${gitweb_baseurl}${repodir};a=shortlog;h=${3}"
repoprefix=$(git config hooks.irc.prefix || git config hooks.emailprefix || echo "[$repo]")
# Get the user information
# If $GL_USER is set we're running under gitolite.
if [ -n "$GL_USER" ]; then
user=$GL_USER
else
user=$USER
fi
case ${change_type} in
"create")
header="${repoprefix} $user ${change_type}d the $refname_type $short_refname: ${head}."
;;
"delete")
header="${repoprefix} $user ${change_type}d the $refname_type $short_refname."
;;
"update")
num=$(git log --pretty=oneline ${1}..${2}|wc -l)
branch=${3/refs\/heads\//}
if [ ${num} -gt 1 ]; then
s="s"
fi
header="${repoprefix} $user pushed ${num} new commit${s} to ${branch}: ${head}"
;;
*)
# most weird ... this should never happen
echo >&2 "*** Unknown type of update to $refname ($rev_type)"
echo >&2 "*** - notifications will probably screw up."
;;
esac
# Run once for each channel in the notify list:
for chan in $channels
do
echo "${chan} ${header}" | nc -w 1 localhost 5050
if [ "${change_type}" == "update" ]; then
if [ ${num} -lt ${max} ]; then
git log --pretty=format:"${chan} %h by %an: %s" ${1}..${2} | nc -w 1 localhost 5050
fi
fi
done
}
# MAIN PROGRAM
# Read all refs from stdin, notify for each
while read line; do
set -- $line
notify $*
RET=$?
done
exit $RET
@init-js
Copy link

init-js commented Oct 10, 2016

Are there any licensing terms associated with this file? Assuming you are the original author, would you allow it or derivatives of it to be included in a GPL-licensed repo ?

edit: I see the disclaimer above points to GIT-Bot, which is licensed under BSD3. I believe your code would qualify as a significant contribution to the original (which is a 10 line script).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment