CIA hook for contrib/

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]