Summary: * The CIA hooks for git are presently dusty and somewhat broken. * I am requesting that they be given a home in git contrib/. * I am supplying working, updated versions. * I will accept maintainance responsibility if required. Many listmembers will be aware of CIA.vc, a useful service that echoes commits from open-source projects to IRC channels and maintains various interesting statistics on commit activity. Under git, it is supported by one of two hook scripts: ciabot.pl and ciabot.pl. In the course of migrating the GPSD project from Subversion to git, I discovered that the 2006 version of ciabot.sh available from CIA.vc is broken. It requires, but does not have, a PATH adjustment to cope with the fact that various git tools it uses now go in a commands directory private to git. The 2008 version of ciabot.sh made available on the git wiki also has no PATH adjustment. Upon investigating further, I find that ciabot.sh seems to be a derivative of ciabot.pl, which is a dangling bit of the moribund Cogito project. I have been unable to get responses from the authors of either ciabot.sh or ciabot.pl. A fixed and working version in shell is enclosed. It has some advantages over the 2006 and 2008 versions: * It uses only POSIX features. Thus, it will work with Debian/Ubuntu dash and BSD's non-bash shells. * It's faster, because it uses a lighter-weight shell. * It's much closer to being autoconfiguring. In the normal case, all the person installing an instance need supply is the project name. * It is considerably better documented. * It can support cgit as well as gitweb installations. I am also enclosing a rewrite in Python. This has a serious functional advantage over either Perl or sh; the batteries-included effect of the Python libraries means it's not dependent on things like the path location of sendmail or whether the hosting site will allow it to run wget. I think the broad usage of CIA.vc justifies adding one of these as an official ciabot hook to git contrib/, and am so proposing. Should it be required, I will accept maintainance responsibility; I expect the amount of effort involved to be minimal. Both versions have been live-tested on the GPSD project repo. The Python version is now in production use there. Code is enclosed. -- <a href="http://www.catb.org/~esr/">Eric S. Raymond</a>
Attachment:
ciabot.sh
Description: Bourne shell script
#!/usr/bin/env python # Distributed under the terms of the GNU General Public License v2 # Copyright (c) 2010 Eric S. Raymond <esr@xxxxxxxxxxx> # # This script contains porcelain and porcelain byproducts. # It's Python because the Python standard libraries avoid portability/security # issues raised by callouts in the ancestral Perl and sh scripts. It should # be compatible back to Python 2.1.5. # # It is meant to be run either on a post-commit hook or in an update # hook: # # post-commit: It queries for current HEAD and latest commit ID to get the # information it needs. # # update: You have to call it once per merged commit: # # refname=$1 # oldhead=$2 # newhead=$3 # for merged in $(git rev-list ${oldhead}..${newhead} | tac) ; do # /path/to/ciabot.py ${refname} ${merged} # done # # Note: this script uses mail, not XML-RPC, in order to avoid stalling # until timeout when the XML-RPC server is down. # # Call with -n to see the notification mail dumped to stdout rather # than shipped to CIA. # import os, sys, commands, socket, urllib # # The project as known to CIA. You will want to change this: # project="GPSD" # # You may not need to change these: # # Name of the repository. # You can hardwire this to make the script faster. repo = os.path.basename(os.getcwd()) # Fully-qualified domain name of this host. # You can hardwire this to make the script faster. host = socket.getfqdn() # 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 # through gitweb or something similar. The default will probably # work if you have a typical gitweb/cgit setup. # #urlprefix="http://%(host)s/cgi-bin/gitweb.cgi?p=%(repo)s;a=commit;h="%locals() urlprefix="http://%(host)s/cgi-bin/cgit.cgi/%(repo)s/commit/?id="%locals() # # No user-serviceable parts below this line: # def do(command): return commands.getstatusoutput(command)[1] # 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@xxxxxx" # Identify the generator script. # Should only change when the script itself has a new home generator="http://www.catb.org/~esr/ciabot.sh" # Should add to the command path both places sendmail is likely to lurk, # and the git private command directory. os.environ["PATH"] += ":/usr/sbin/:" + do("git --exec-path") # Call this script with -n tp dump the notification mail to stdout mailit = True if sys.argv[1] == '-n': mailit = False sys.argv.pop(1) # Script wants a reference to head followed by the commit ID to notify about. if len(sys.argv) == 1: refname = do("git symbolic-ref HEAD 2>/dev/null") merged = do("git rev-parse HEAD") else: refname = sys.argv[1] merged = sys.argv[2] # This tries to turn your gitwebbish URL into a tinyurl so it will take up # less space on the IRC notification line. You can tweak the tinyfier # service if you need to. tinyifier = "http://tinyurl.com/api-create.php?url=" try: url = open(urllib.urlretrieve(tinyifier + urlprefix + merged)[0]).read() except: url = urlprefix + merged refname = os.path.basename(refname) gitver = do("git --version").split()[0] # Git version number rev = do("git describe ${merged} 2>/dev/null") or merged[:12] rawcommit = do("git cat-file commit " + merged) files=do("git diff-tree -r --name-only '"+ merged +"' | sed -e '1d' -e 's-.*-<file>&</file>-'") inheader = True headers = {} logmessage = "" for line in rawcommit.split("\n"): if inheader: if line: fields = line.split() headers[fields[0]] = " ".join(fields[1:]) else: inheader = False else: logmessage = line break (author, ts) = headers["author"].split(">") author = author.replace("<", "").split("@")[0].split()[-1] ts = ts.strip() out = '''\ <message> <generator> <name>CIA Shell client for Git</name> <version>%(gitver)s</version> <url>%(generator)s</url> </generator> <source> <project>%(project)s</project> <branch>%(repo)s:%(refname)s</branch> </source> <timestamp>%(ts)s</timestamp> <body> <commit> <author>%(author)s</author> <revision>%(rev)s</revision> <files> %(files)s </files> <log>%(logmessage)s %(url)s</log> <url>%(url)s</url> </commit> </body> </message> ''' % locals() message = '''\ Message-ID: <%(merged)s.%(author)s@%(project)s> From: %(fromaddr)s To: %(toaddr)s Content-type: text/xml Subject: DeliverXML %(out)s''' % locals() if mailit: import smtplib server = smtplib.SMTP('localhost') server.sendmail(fromaddr, [toaddr], message) server.quit() else: print message #End