diff options
Diffstat (limited to 'contrib/ciabot')
-rw-r--r-- | contrib/ciabot/INSTALL | 54 | ||||
-rw-r--r-- | contrib/ciabot/README | 3 | ||||
-rwxr-xr-x | contrib/ciabot/ciabot.py | 183 | ||||
-rwxr-xr-x | contrib/ciabot/ciabot.sh | 133 |
4 files changed, 250 insertions, 123 deletions
diff --git a/contrib/ciabot/INSTALL b/contrib/ciabot/INSTALL new file mode 100644 index 0000000000..7222961d35 --- /dev/null +++ b/contrib/ciabot/INSTALL @@ -0,0 +1,54 @@ += Installation instructions = + +Two scripts are included. The Python one (ciabot.py) is faster and +more capable; the shell one (ciabot.sh) is a fallback in case Python +gives your git hosting site indigestion. (I know of no such sites.) + +It is no longer necessary to modify the script in order to put it +in place; in fact, this is now discouraged. It is entirely +configurable with the following git config variables: + +ciabot.project = name of the project +ciabot.repo = name of the project repo for gitweb/cgit purposes +ciabot.xmlrpc = if true, ship notifications via XML-RPC +ciabot.revformat = format in which the revision is shown + +The revformat variable may have the following values +raw -> full hex ID of commit +short -> first 12 chars of hex ID +describe -> describe relative to last tag, falling back to short + +ciabot.project defaults to the directory name of the repository toplevel. +ciabot.repo defaults to ciabot.project lowercased. +ciabot.xmlrpc defaults to True +ciabot.revformat defaults to 'describe'. + +This means that in the normal case you need not do any configuration at all, +however setting ciabot.project will allow the hook to run slightly faster. + +Once you've set these variables, try your script with -n to see the +notification message dumped to stdout and verify that it looks sane. + +To live-test these scripts, your project needs to have been registered with +the CIA site. Here are the steps: + +1. Open an IRC window on irc://freenode/commits or your registered + project IRC channel. + +2. Run ciabot.py and/or ciabot.sh from any directory under git + control. + +You should see a notification on the channel for your most recent commit. + +After verifying correct function, install one of these scripts either +in a post-commit hook or in an update hook. + +In post-commit, run it without arguments. It will query for +current HEAD and the latest commit ID to get the information it +needs. + +In update, call it with a refname followed by a list of commits: +You want to reverse the order git rev-list emits because it lists +from most recent to oldest. + +/path/to/ciabot.py ${refname} $(git rev-list ${oldhead}..${newhead} | tac) diff --git a/contrib/ciabot/README b/contrib/ciabot/README index 3b916acece..2dfe1f91f5 100644 --- a/contrib/ciabot/README +++ b/contrib/ciabot/README @@ -8,5 +8,4 @@ You probably want the Python version; it's faster, more capable, and better documented. The shell version is maintained only as a fallback for use on hosting sites that don't permit Python hook scripts. -You will find installation instructions for each script in its comment -header. +See the file INSTALL for installation instructions. diff --git a/contrib/ciabot/ciabot.py b/contrib/ciabot/ciabot.py index 9775dffb5d..36b5665ff8 100755 --- a/contrib/ciabot/ciabot.py +++ b/contrib/ciabot/ciabot.py @@ -10,44 +10,51 @@ # usage: ciabot.py [-V] [-n] [-p projectname] [refname [commits...]] # # This script is meant to be run either in a post-commit hook or in an -# update hook. If there's nothing unusual about your hosting setup, -# you can specify the project name with a -p option and avoid having -# to modify this script. Try it with -n to see the notification mail -# dumped to stdout and verify that it looks sane. With -V it dumps its -# version and exits. +# update hook. Try it with -n to see the notification mail dumped to +# stdout and verify that it looks sane. With -V it dumps its version +# and exits. # -# In post-commit, run it without arguments (other than possibly a -p -# option). It will query for current HEAD and the latest commit ID to -# get the information it needs. +# In post-commit, run it without arguments. It will query for +# current HEAD and the latest commit ID to get the information it +# needs. # # In update, call it with a refname followed by a list of commits: -# You want to reverse the order git rev-list emits becxause it lists +# You want to reverse the order git rev-list emits because it lists # from most recent to oldest. # # /path/to/ciabot.py ${refname} $(git rev-list ${oldhead}..${newhead} | tac) # -# Note: this script uses mail, not XML-RPC, in order to avoid stalling -# until timeout when the CIA XML-RPC server is down. +# Configuration variables affecting this script: # - +# ciabot.project = name of the project +# ciabot.repo = name of the project repo for gitweb/cgit purposes +# ciabot.xmlrpc = if true (default), ship notifications via XML-RPC +# ciabot.revformat = format in which the revision is shown # -# The project as known to CIA. You will either want to change this -# or invoke the script with a -p option to set it. +# ciabot.project defaults to the directory name of the repository toplevel. +# ciabot.repo defaults to ciabot.project lowercased. # -project=None - +# This means that in the normal case you need not do any configuration at all, +# but setting the project name will speed it up slightly. +# +# The revformat variable may have the following values +# raw -> full hex ID of commit +# short -> first 12 chars of hex ID +# describe = -> describe relative to last tag, falling back to short +# The default is 'describe'. # -# You may not need to change these: +# Note: the CIA project now says only XML-RPC is reliable, so +# we default to that. # -import os, sys, commands, socket, urllib -# Name of the repository. -# You can hardwire this to make the script faster. -repo = os.path.basename(os.getcwd()) +import sys +if sys.hexversion < 0x02000000: + # The limiter is the xml.sax module + sys.stderr.write("ciabot.py: requires Python 2.0.0 or later.\n") + sys.exit(1) -# Fully-qualified domain name of this host. -# You can hardwire this to make the script faster. -host = socket.getfqdn() +import os, commands, socket, urllib +from xml.sax.saxutils import escape # Changeset URL prefix for your repo: when the commit ID is appended # to this, it should point at a CGI that will display the commit @@ -72,7 +79,7 @@ xml = '''\ <message> <generator> <name>CIA Python client for Git</name> - <version>%(gitver)s</version> + <version>%(version)s</version> <url>%(generator)s</url> </generator> <source> @@ -98,19 +105,18 @@ xml = '''\ # No user-serviceable parts below this line: # -# Addresses for the e-mail. The from address is a dummy, since CIA -# will never reply to this mail. -fromaddr = "CIABOT-NOREPLY@" + host -toaddr = "cia@cia.navi.cx" +# Where to ship e-mail notifications. +toaddr = "cia@cia.vc" # Identify the generator script. # Should only change when the script itself gets a new home and maintainer. -generator="http://www.catb.org/~esr/ciabot.py" +generator = "http://www.catb.org/~esr/ciabot.py" +version = "3.6" def do(command): return commands.getstatusoutput(command)[1] -def report(refname, merged): +def report(refname, merged, xmlrpc=True): "Generate a commit notification to be reported to CIA" # Try to tinyfy a reference to a web view for this commit. @@ -121,32 +127,27 @@ def report(refname, merged): branch = os.path.basename(refname) - # Compute a shortnane for the revision - rev = do("git describe '"+ merged +"' 2>/dev/null") or merged[:12] - - # Extract the neta-information for the commit - rawcommit = do("git cat-file commit " + merged) + # Compute a description for the revision + if revformat == 'raw': + rev = merged + elif revformat == 'short': + rev = '' + else: # revformat == 'describe' + rev = do("git describe %s 2>/dev/null" % merged) + if not rev: + rev = merged[:12] + + # Extract the meta-information for the commit files=do("git diff-tree -r --name-only '"+ merged +"' | sed -e '1d' -e 's-.*-<file>&</file>-'") - inheader = True - headers = {} - logmsg = "" - for line in rawcommit.split("\n"): - if inheader: - if line: - fields = line.split() - headers[fields[0]] = " ".join(fields[1:]) - else: - inheader = False - else: - logmsg = line - break - (author, ts) = headers["author"].split(">") + metainfo = do("git log -1 '--pretty=format:%an <%ae>%n%at%n%s' " + merged) + (author, ts, logmsg) = metainfo.split("\n") + logmsg = escape(logmsg) - # This discards the part of the authors addrsss after @. - # Might be bnicece to ship the full email address, if not + # This discards the part of the author's address after @. + # Might be be nice to ship the full email address, if not # for spammers' address harvesters - getting this wrong # would make the freenode #commits channel into harvester heaven. - author = author.replace("<", "").split("@")[0].split()[-1] + author = escape(author.replace("<", "").split("@")[0].split()[-1]) # This ignores the timezone. Not clear what to do with it... ts = ts.strip().split()[0] @@ -155,8 +156,7 @@ def report(refname, merged): context.update(globals()) out = xml % context - - message = '''\ + mail = '''\ Message-ID: <%(merged)s.%(author)s@%(project)s> From: %(fromaddr)s To: %(toaddr)s @@ -165,34 +165,56 @@ Subject: DeliverXML %(out)s''' % locals() - return message + if xmlrpc: + return out + else: + return mail if __name__ == "__main__": import getopt + # Get all config variables + revformat = do("git config --get ciabot.revformat") + project = do("git config --get ciabot.project") + repo = do("git config --get ciabot.repo") + xmlrpc = do("git config --get ciabot.xmlrpc") + xmlrpc = not (xmlrpc and xmlrpc == "false") + + host = socket.getfqdn() + fromaddr = "CIABOT-NOREPLY@" + host + try: - (options, arguments) = getopt.getopt(sys.argv[1:], "np:V") + (options, arguments) = getopt.getopt(sys.argv[1:], "np:xV") except getopt.GetoptError, msg: print "ciabot.py: " + str(msg) raise SystemExit, 1 - mailit = True + notify = True for (switch, val) in options: if switch == '-p': project = val elif switch == '-n': - mailit = False + notify = False + elif switch == '-x': + xmlrpc = True elif switch == '-V': - print "ciabot.py: version 3.2" + print "ciabot.py: version", version sys.exit(0) - # Cough and die if user has not specified a project + # The project variable defaults to the name of the repository toplevel. if not project: - sys.stderr.write("ciabot.py: no project specified, bailing out.\n") - sys.exit(1) - - # We'll need the git version number. - gitver = do("git --version").split()[0] + here = os.getcwd() + while True: + if os.path.exists(os.path.join(here, ".git")): + project = os.path.basename(here) + break + elif here == '/': + sys.stderr.write("ciabot.py: no .git below root!\n") + sys.exit(1) + here = os.path.dirname(here) + + if not repo: + repo = project.lower() urlprefix = urlprefix % globals() @@ -205,18 +227,29 @@ if __name__ == "__main__": refname = arguments[0] merges = arguments[1:] - if mailit: - import smtplib - server = smtplib.SMTP('localhost') + if notify: + if xmlrpc: + import xmlrpclib + server = xmlrpclib.Server('http://cia.vc/RPC2'); + else: + import smtplib + server = smtplib.SMTP('localhost') for merged in merges: - message = report(refname, merged) - if mailit: - server.sendmail(fromaddr, [toaddr], message) - else: + message = report(refname, merged, xmlrpc) + if not notify: print message + elif xmlrpc: + try: + # RPC server is flaky, this can fail due to timeout. + server.hub.deliver(message) + except socket.error, e: + sys.stderr.write("%s\n" % e) + else: + server.sendmail(fromaddr, [toaddr], message) - if mailit: - server.quit() + if notify: + if not xmlrpc: + server.quit() #End diff --git a/contrib/ciabot/ciabot.sh b/contrib/ciabot/ciabot.sh index eb87bba38e..3fbbc534ae 100755 --- a/contrib/ciabot/ciabot.sh +++ b/contrib/ciabot/ciabot.sh @@ -3,6 +3,8 @@ # Copyright (c) 2006 Fernando J. Pereda <ferdy@gentoo.org> # Copyright (c) 2008 Natanael Copa <natanael.copa@gmail.com> # Copyright (c) 2010 Eric S. Raymond <esr@thyrsus.com> +# Assistance and review by Petr Baudis, author of ciabot.pl, +# is gratefully acknowledged. # # This is a version 3.x of ciabot.sh; use -V to find the exact # version. Versions 1 and 2 were shipped in 2006 and 2008 and are not @@ -11,6 +13,7 @@ # Note: This script should be considered obsolete. # There is a faster, better-documented rewrite in Python: find it as ciabot.py # Use this only if your hosting site forbids Python hooks. +# It requires: git(1), hostname(1), cut(1), sendmail(1), and wget(1). # # Originally based on Git ciabot.pl by Petr Baudis. # This script contains porcelain and porcelain byproducts. @@ -18,15 +21,13 @@ # usage: ciabot.sh [-V] [-n] [-p projectname] [refname commit] # # This script is meant to be run either in a post-commit hook or in an -# update hook. If there's nothing unusual about your hosting setup, -# you can specify the project name with a -p option and avoid having -# to modify this script. Try it with -n first to see the notification -# mail dumped to stdout and verify that it looks sane. Use -V to dump -# the version and exit. +# update hook. Try it with -n to see the notification mail dumped to +# stdout and verify that it looks sane. With -V it dumps its version +# and exits. # -# In post-commit, run it without arguments (other than possibly a -p -# option). It will query for current HEAD and the latest commit ID to -# get the information it needs. +# In post-commit, run it without arguments. It will query for +# current HEAD and the latest commit ID to get the information it +# needs. # # In update, you have to call it once per merged commit: # @@ -34,33 +35,76 @@ # oldhead=$2 # newhead=$3 # for merged in $(git rev-list ${oldhead}..${newhead} | tac) ; do -# /path/to/ciabot.bash ${refname} ${merged} +# /path/to/ciabot.sh ${refname} ${merged} # done # -# The reason for the tac call ids that git rev-list emits commits from +# The reason for the tac call is that git rev-list emits commits from # most recent to least - better to ship notifactions from oldest to newest. # -# Note: this script uses mail, not XML-RPC, in order to avoid stalling -# until timeout when the CIA XML-RPC server is down. +# Configuration variables affecting this script: # - +# ciabot.project = name of the project +# ciabot.repo = name of the project repo for gitweb/cgit purposes +# ciabot.revformat = format in which the revision is shown # -# The project as known to CIA. You will either want to change this -# or set the project name with a -p option. +# ciabot.project defaults to the directory name of the repository toplevel. +# ciabot.repo defaults to ciabot.project lowercased. # -project= - +# This means that in the normal case you need not do any configuration at all, +# but setting the project name will speed it up slightly. # -# You may not need to change these: +# The revformat variable may have the following values +# raw -> full hex ID of commit +# short -> first 12 chars of hex ID +# describe = -> describe relative to last tag, falling back to short +# The default is 'describe'. # +# Note: the shell ancestors of this script used mail, not XML-RPC, in +# order to avoid stalling until timeout when the CIA XML-RPC server is +# down. It is unknown whether this is still an issue in 2010, but +# XML-RPC would be annoying to do from sh in any case. (XML-RPC does +# have the advantage that it guarantees notification of multiple commits +# shpped from an update in their actual order.) +# + +# The project as known to CIA. You can set this with a -p option, +# or let it default to the directory name of the repo toplevel. +project=$(git config --get ciabot.project) + +if [ -z $project ] +then + here=`pwd`; + while :; do + if [ -d $here/.git ] + then + project=`basename $here` + break + elif [ $here = '/' ] + then + echo "ciabot.sh: no .git below root!" + exit 1 + fi + here=`dirname $here` + done +fi -# Name of the repository. -# You can hardwire this to make the script faster. -repo="`basename ${PWD}`" +# Name of the repo for gitweb/cgit purposes +repo=$(git config --get ciabot.repo) +[ -z $repo] && repo=$(echo "${project}" | tr '[A-Z]' '[a-z]') -# Fully qualified domain name of the repo host. -# You can hardwire this to make the script faster. -host=`hostname --fqdn` +# What revision format do we want in the summary? +revformat=$(git config --get ciabot.revformat) + +# Fully qualified domain name of the repo host. You can hardwire this +# to make the script faster. The -f option works under Linux and FreeBSD, +# but not OpenBSD and NetBSD. But under OpenBSD and NetBSD, +# hostname without options gives the FQDN. +if hostname -f >/dev/null 2>&1 +then + hostname=`hostname -f` +else + hostname=`hostname` +fi # Changeset URL prefix for your repo: when the commit ID is appended # to this, it should point at a CGI that will display the commit @@ -73,13 +117,14 @@ urlprefix="http://${host}/cgi-bin/cgit.cgi/${repo}/commit/?id=" # You probably will not need to change the following: # -# Identify the script. Should change only when the script itself -# gets a new home and maintainer. +# Identify the script. The 'generator' variable should change only +# when the script itself gets a new home and maintainer. generator="http://www.catb.org/~esr/ciabot/ciabot.sh" +version=3.5 # Addresses for the e-mail -from="CIABOT-NOREPLY@${host}" -to="cia@cia.navi.cx" +from="CIABOT-NOREPLY@${hostname}" +to="cia@cia.vc" # SMTP client to use - may need to edit the absolute pathname for your system sendmail="sendmail -t -f ${from}" @@ -97,7 +142,7 @@ do case $opt in p) project=$2; shift ; shift ;; n) mode=dumpit; shift ;; - V) echo "ciabot.sh: version 3.2"; exit 0; shift ;; + V) echo "ciabot.sh: version $version"; exit 0; shift ;; esac done @@ -128,33 +173,29 @@ fi refname=${refname##refs/heads/} -gitver=$(git --version) -gitver=${gitver##* } - -rev=$(git describe ${merged} 2>/dev/null) -# ${merged:0:12} was the only bashism left in the 2008 version of this -# script, according to checkbashisms. Replace it with ${merged} here -# because it was just a fallback anyway, and it's worth accepting a -# longer fallback for faster execution and removing the bash -# dependency. -[ -z ${rev} ] && rev=${merged} +case $revformat in +raw) rev=$merged ;; +short) rev='' ;; +*) rev=$(git describe ${merged} 2>/dev/null) ;; +esac +[ -z ${rev} ] && rev=$(echo "$merged" | cut -c 1-12) -# This discards the part of the author's address after @. +# We discard the part of the author's address after @. # Might be nice to ship the full email address, if not # for spammers' address harvesters - getting this wrong # would make the freenode #commits channel into harvester heaven. -rawcommit=$(git cat-file commit ${merged}) -author=$(echo "$rawcommit" | sed -n -e '/^author .*<\([^@]*\).*$/s--\1-p') -logmessage=$(echo "$rawcommit" | sed -e '1,/^$/d' | head -n 1) -logmessage=$(echo "$logmessage" | sed 's/\&/&\;/g; s/</<\;/g; s/>/>\;/g') -ts=$(echo "$rawcommit" | sed -n -e '/^author .*> \([0-9]\+\).*$/s--\1-p') +author=$(git log -1 '--pretty=format:%an <%ae>' $merged) +author=$(echo "$author" | sed -n -e '/^.*<\([^@]*\).*$/s--\1-p') + +logmessage=$(git log -1 '--pretty=format:%s' $merged) +ts=$(git log -1 '--pretty=format:%at' $merged) files=$(git diff-tree -r --name-only ${merged} | sed -e '1d' -e 's-.*-<file>&</file>-') out=" <message> <generator> <name>CIA Shell client for Git</name> - <version>${gitver}</version> + <version>${version}</version> <url>${generator}</url> </generator> <source> |