Skip to content

Instantly share code, notes, and snippets.

@GregSutcliffe
Created May 4, 2012 16:14
Show Gist options
  • Save GregSutcliffe/2595830 to your computer and use it in GitHub Desktop.
Save GregSutcliffe/2595830 to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# IRC notification post-receive hook.
# Based on https://wiki.icinga.org/display/community/GIT+Commit+Bot
#
# Author: Mikael Fridh <frimik@gmail.com>
# Modified by: Greg Sutcliffe <gsutcliffe@ibahn.com
#
# This script pulls out the commit information and sends it to
# the RemoteCtl plugin in rbot via quassel.office:7268 using
# a preconfigured user via:
#
# user create puppet password
# permissions set +remotectl for puppet
# permissions set +basics::talk::do for puppet
#
# FIXME read user, password, host and port from git config
# TODO add hooks.gitweb.url to point to http://example.com/gitweb
#
# 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.
#
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
# 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/?p=gitolite/"
else
# non-gitolite repo, no special prefix
gitweb_baseurl="http://git.example.com/gitweb/?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}"
# ETV override, we don't use gitweb
url=""
head=""
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
channels=$(git config hooks.irc.channel)
auth=$(git config hooks.irc.auth)
host=$(echo $auth|cut -d':' -f1)
port=$(echo $auth|cut -d':' -f2)
user=$(echo $auth|cut -d':' -f3)
pass=$(echo $auth|cut -d':' -f4)
# Run once for each channel in the notify list:
for chan in $channels
do
echo "${header}" | rbot-remote -u "${user}" -p "${pass}" -d "${chan}" -r "druby://${host}:${port}" 2>&1 >/dev/null
if [ "${change_type}" == "update" ]; then
if [ ${num} -lt ${max} ]; then
git log --pretty=format:"%h by %an: %s" ${1}..${2} | rbot-remote -u "${user}" -p "${pass}" -d "${chan}" -r "druby://${host}:${port}" 2>&1 >/dev/null
fi
fi
done
}
# MAIN PROGRAM
# Read all refs from stdin, notify for each
while read line; do
set -- $line
notify $*
RET=$?
done
exit $RET
# vim: set filetype=sh:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment