contrib/ciabot: Get ciabot configuration from git variables

These changes remove all need to modify the ciabot scripts for installation. Instead, per-project configuration can be dome via variables in a [ciabot] section of the config file. Also, correct for the new server address. Signed-off-by: Eric S. Raymond <esr@thyrsus.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Eric S. Raymond committed Aug 22, 2012 at 06:52 UTC c142616fb2152d7887f9c38ff20e07167d31b0c8
2 files changed +156 -118
contrib/ciabot/ciabot.py
+89 -72
@@ -11,43 +11,41 @@
11 #
12 # This script is meant to be run either in a post-commit hook or in an
13 # update hook. If there's nothing unusual about your hosting setup,
14 -# you can specify the project name with a -p option and avoid having
15 -# to modify this script. Try it with -n to see the notification mail
16 -# dumped to stdout and verify that it looks sane. With -V it dumps its
17 -# version and exits.
14 +# you can specify the project name and repo with config variables and
15 +# avoid having to modify this script. Try it with -n to see the
16 +# notification mail dumped to stdout and verify that it looks
17 +# sane. With -V it dumps its version and exits.
18 #
19 -# In post-commit, run it without arguments (other than possibly a -p
20 -# option). It will query for current HEAD and the latest commit ID to
21 -# get the information it needs.
19 +# In post-commit, run it without arguments. It will query for
20 +# current HEAD and the latest commit ID to get the information it
21 +# needs.
22 #
23 # In update, call it with a refname followed by a list of commits:
24 -# You want to reverse the order git rev-list emits becxause it lists
24 +# You want to reverse the order git rev-list emits because it lists
25 # from most recent to oldest.
26 #
27 # /path/to/ciabot.py ${refname} $(git rev-list ${oldhead}..${newhead} | tac)
28 #
29 -# Note: this script uses mail, not XML-RPC, in order to avoid stalling
30 -# until timeout when the CIA XML-RPC server is down.
29 +# Configuration variables affecting this script:
30 +# ciabot.project = name of the project (required)
31 +# ciabot.repo = name of the project repo for gitweb/cgit purposes
32 +# ciabot.xmlrpc = if true (default), ship notifications via XML-RPC
33 +# ciabot.revformat = format in which the revision is shown
34 #
32 -
33 -#
34 -# The project as known to CIA. You will either want to change this
35 -# or invoke the script with a -p option to set it.
35 +# The ciabot.repo value defaults to ciabot.project lowercased.
36 #
37 -project=None
38 -
37 +# The revformat variable may have the following values
38 +# raw -> full hex ID of commit
39 +# short -> first 12 chars of hex ID
40 +# describe = -> describe relative to last tag, falling back to short
41 +# The default is 'describe'.
42 #
40 -# You may not need to change these:
43 +# Note: the CIA project now says only XML-RPC is reliable, so
44 +# we default to that.
45 #
42 -import os, sys, commands, socket, urllib
43 -
44 -# Name of the repository.
45 -# You can hardwire this to make the script faster.
46 -repo = os.path.basename(os.getcwd())
46
48 -# Fully-qualified domain name of this host.
49 -# You can hardwire this to make the script faster.
50 -host = socket.getfqdn()
47 +import os, sys, commands, socket, urllib
48 +from xml.sax.saxutils import escape
49
50 # Changeset URL prefix for your repo: when the commit ID is appended
51 # to this, it should point at a CGI that will display the commit
@@ -72,7 +70,7 @@ xml = '''\
70 <message>
71 <generator>
72 <name>CIA Python client for Git</name>
75 - <version>%(gitver)s</version>
73 + <version>%(version)s</version>
74 <url>%(generator)s</url>
75 </generator>
76 <source>
@@ -98,19 +96,18 @@ xml = '''\
96 # No user-serviceable parts below this line:
97 #
98
101 -# Addresses for the e-mail. The from address is a dummy, since CIA
102 -# will never reply to this mail.
103 -fromaddr = "CIABOT-NOREPLY@" + host
104 -toaddr = "cia@cia.navi.cx"
99 +# Where to ship e-mail notifications.
100 +toaddr = "cia@cia.vc"
101
102 # Identify the generator script.
103 # Should only change when the script itself gets a new home and maintainer.
108 -generator="http://www.catb.org/~esr/ciabot.py"
104 +generator = "http://www.catb.org/~esr/ciabot.py"
105 +version = "3.5"
106
107 def do(command):
108 return commands.getstatusoutput(command)[1]
109
113 -def report(refname, merged):
110 +def report(refname, merged, xmlrpc=True):
111 "Generate a commit notification to be reported to CIA"
112
113 # Try to tinyfy a reference to a web view for this commit.
@@ -121,32 +118,27 @@ def report(refname, merged):
118
119 branch = os.path.basename(refname)
120
124 - # Compute a shortnane for the revision
125 - rev = do("git describe '"+ merged +"' 2>/dev/null") or merged[:12]
126 -
127 - # Extract the neta-information for the commit
128 - rawcommit = do("git cat-file commit " + merged)
121 + # Compute a description for the revision
122 + if revformat == 'raw':
123 + rev = merged
124 + elif revformat == 'short':
125 + rev = ''
126 + else: # revformat == 'describe'
127 + rev = do("git describe %s 2>/dev/null" % merged)
128 + if not rev:
129 + rev = merged[:12]
130 +
131 + # Extract the meta-information for the commit
132 files=do("git diff-tree -r --name-only '"+ merged +"' | sed -e '1d' -e 's-.*-<file>&</file>-'")
130 - inheader = True
131 - headers = {}
132 - logmsg = ""
133 - for line in rawcommit.split("\n"):
134 - if inheader:
135 - if line:
136 - fields = line.split()
137 - headers[fields[0]] = " ".join(fields[1:])
138 - else:
139 - inheader = False
140 - else:
141 - logmsg = line
142 - break
143 - (author, ts) = headers["author"].split(">")
133 + metainfo = do("git log -1 '--pretty=format:%an <%ae>%n%at%n%s' " + merged)
134 + (author, ts, logmsg) = metainfo.split("\n")
135 + logmsg = escape(logmsg)
136
145 - # This discards the part of the authors addrsss after @.
146 - # Might be bnicece to ship the full email address, if not
137 + # This discards the part of the author's address after @.
138 + # Might be be nice to ship the full email address, if not
139 # for spammers' address harvesters - getting this wrong
140 # would make the freenode #commits channel into harvester heaven.
149 - author = author.replace("<", "").split("@")[0].split()[-1]
141 + author = escape(author.replace("<", "").split("@")[0].split()[-1])
142
143 # This ignores the timezone. Not clear what to do with it...
144 ts = ts.strip().split()[0]
@@ -155,8 +147,7 @@ def report(refname, merged):
147 context.update(globals())
148
149 out = xml % context
158 -
159 - message = '''\
150 + mail = '''\
151 Message-ID: <%(merged)s.%(author)s@%(project)s>
152 From: %(fromaddr)s
153 To: %(toaddr)s
@@ -165,25 +156,40 @@ Subject: DeliverXML
156
157 %(out)s''' % locals()
158
168 - return message
159 + if xmlrpc:
160 + return out
161 + else:
162 + return mail
163
164 if __name__ == "__main__":
165 import getopt
166
167 + # Get all config variables
168 + revformat = do("git config --get ciabot.revformat")
169 + project = do("git config --get ciabot.project")
170 + repo = do("git config --get ciabot.repo")
171 + xmlrpc = do("git config --get ciabot.xmlrpc")
172 + xmlrpc = not (xmlrpc and xmlrpc == "false")
173 +
174 + host = socket.getfqdn()
175 + fromaddr = "CIABOT-NOREPLY@" + host
176 +
177 try:
174 - (options, arguments) = getopt.getopt(sys.argv[1:], "np:V")
178 + (options, arguments) = getopt.getopt(sys.argv[1:], "np:xV")
179 except getopt.GetoptError, msg:
180 print "ciabot.py: " + str(msg)
181 raise SystemExit, 1
182
179 - mailit = True
183 + notify = True
184 for (switch, val) in options:
185 if switch == '-p':
186 project = val
187 elif switch == '-n':
184 - mailit = False
188 + notify = False
189 + elif switch == '-x':
190 + xmlrpc = True
191 elif switch == '-V':
186 - print "ciabot.py: version 3.2"
192 + print "ciabot.py: version", version
193 sys.exit(0)
194
195 # Cough and die if user has not specified a project
@@ -191,8 +197,8 @@ if __name__ == "__main__":
197 sys.stderr.write("ciabot.py: no project specified, bailing out.\n")
198 sys.exit(1)
199
194 - # We'll need the git version number.
195 - gitver = do("git --version").split()[0]
200 + if not repo:
201 + repo = project.lower()
202
203 urlprefix = urlprefix % globals()
204
@@ -205,18 +211,29 @@ if __name__ == "__main__":
211 refname = arguments[0]
212 merges = arguments[1:]
213
208 - if mailit:
209 - import smtplib
210 - server = smtplib.SMTP('localhost')
214 + if notify:
215 + if xmlrpc:
216 + import xmlrpclib
217 + server = xmlrpclib.Server('http://cia.vc/RPC2');
218 + else:
219 + import smtplib
220 + server = smtplib.SMTP('localhost')
221
222 for merged in merges:
213 - message = report(refname, merged)
214 - if mailit:
215 - server.sendmail(fromaddr, [toaddr], message)
216 - else:
223 + message = report(refname, merged, xmlrpc)
224 + if not notify:
225 print message
226 + elif xmlrpc:
227 + try:
228 + # RPC server is flaky, this can fail due to timeout.
229 + server.hub.deliver(message)
230 + except socket.error, e:
231 + sys.stderr.write("%s\n" % e)
232 + else:
233 + server.sendmail(fromaddr, [toaddr], message)
234
219 - if mailit:
220 - server.quit()
235 + if notify:
236 + if not xmlrpc:
237 + server.quit()
238
239 #End
contrib/ciabot/ciabot.sh
+67 -46
@@ -3,6 +3,8 @@
3 # Copyright (c) 2006 Fernando J. Pereda <ferdy@gentoo.org>
4 # Copyright (c) 2008 Natanael Copa <natanael.copa@gmail.com>
5 # Copyright (c) 2010 Eric S. Raymond <esr@thyrsus.com>
6 +# Assistance and review by Petr Baudis, author of ciabot.pl,
7 +# is gratefully acknowledged.
8 #
9 # This is a version 3.x of ciabot.sh; use -V to find the exact
10 # version. Versions 1 and 2 were shipped in 2006 and 2008 and are not
@@ -11,6 +13,7 @@
13 # Note: This script should be considered obsolete.
14 # There is a faster, better-documented rewrite in Python: find it as ciabot.py
15 # Use this only if your hosting site forbids Python hooks.
16 +# It requires: git(1), hostname(1), cut(1), sendmail(1), and wget(1).
17 #
18 # Originally based on Git ciabot.pl by Petr Baudis.
19 # This script contains porcelain and porcelain byproducts.
@@ -19,14 +22,14 @@
22 #
23 # This script is meant to be run either in a post-commit hook or in an
24 # update hook. If there's nothing unusual about your hosting setup,
22 -# you can specify the project name with a -p option and avoid having
23 -# to modify this script. Try it with -n first to see the notification
24 -# mail dumped to stdout and verify that it looks sane. Use -V to dump
25 -# the version and exit.
25 +# you can specify the project name and repo with config variables and
26 +# avoid having to modify this script. Try it with -n to see the
27 +# notification mail dumped to stdout and verify that it looks
28 +# sane. With -V it dumps its version and exits.
29 #
27 -# In post-commit, run it without arguments (other than possibly a -p
28 -# option). It will query for current HEAD and the latest commit ID to
29 -# get the information it needs.
30 +# In post-commit, run it without arguments. It will query for
31 +# current HEAD and the latest commit ID to get the information it
32 +# needs.
33 #
34 # In update, you have to call it once per merged commit:
35 #
@@ -34,33 +37,54 @@
37 # oldhead=$2
38 # newhead=$3
39 # for merged in $(git rev-list ${oldhead}..${newhead} | tac) ; do
37 -# /path/to/ciabot.bash ${refname} ${merged}
40 +# /path/to/ciabot.sh ${refname} ${merged}
41 # done
42 #
40 -# The reason for the tac call ids that git rev-list emits commits from
43 +# The reason for the tac call is that git rev-list emits commits from
44 # most recent to least - better to ship notifactions from oldest to newest.
45 #
43 -# Note: this script uses mail, not XML-RPC, in order to avoid stalling
44 -# until timeout when the CIA XML-RPC server is down.
46 +# Configuration variables affecting this script:
47 +# ciabot.project = name of the project (makes -p option unnecessary)
48 +# ciabot.repo = name of the project repo for gitweb/cgit purposes
49 +# ciabot.revformat = format in which the revision is shown
50 #
46 -
47 -#
48 -# The project as known to CIA. You will either want to change this
49 -# or set the project name with a -p option.
51 +# The ciabot.repo defaults to ciabot.project lowercased.
52 #
51 -project=
52 -
53 +# The revformat variable may have the following values
54 +# raw -> full hex ID of commit
55 +# short -> first 12 chars of hex ID
56 +# describe = -> describe relative to last tag, falling back to short
57 +# The default is 'describe'.
58 #
54 -# You may not need to change these:
59 +# Note: the shell ancestors of this script used mail, not XML-RPC, in
60 +# order to avoid stalling until timeout when the CIA XML-RPC server is
61 +# down. It is unknown whether this is still an issue in 2010, but
62 +# XML-RPC would be annoying to do from sh in any case. (XML-RPC does
63 +# have the advantage that it guarantees notification of multiple commits
64 +# shpped from an update in their actual order.)
65 #
66
57 -# Name of the repository.
58 -# You can hardwire this to make the script faster.
59 -repo="`basename ${PWD}`"
67 +# The project as known to CIA. You can also hardwire this or set it with a
68 +# -p option.
69 +project=$(git config --get ciabot.project)
70 +
71 +# Name of the repo for gitweb/cgit purposes
72 +repo=$(git config --get ciabot.repo)
73 +[ -z $repo] && repo=$(echo "${project}" | tr '[A-Z]' '[a-z]')
74 +
75 +# What revision format do we want in the summary?
76 +revformat=$(git config --get ciabot.revformat)
77
61 -# Fully qualified domain name of the repo host.
62 -# You can hardwire this to make the script faster.
63 -host=`hostname --fqdn`
78 +# Fully qualified domain name of the repo host. You can hardwire this
79 +# to make the script faster. The -f option works under Linux and FreeBSD,
80 +# but not OpenBSD and NetBSD. But under OpenBSD and NetBSD,
81 +# hostname without options gives the FQDN.
82 +if hostname -f >/dev/null 2>&1
83 +then
84 + hostname=`hostname -f`
85 +else
86 + hostname=`hostname`
87 +fi
88
89 # Changeset URL prefix for your repo: when the commit ID is appended
90 # to this, it should point at a CGI that will display the commit
@@ -73,13 +97,14 @@ urlprefix="http://${host}/cgi-bin/cgit.cgi/${repo}/commit/?id="
97 # You probably will not need to change the following:
98 #
99
76 -# Identify the script. Should change only when the script itself
77 -# gets a new home and maintainer.
100 +# Identify the script. The 'generator' variable should change only
101 +# when the script itself gets a new home and maintainer.
102 generator="http://www.catb.org/~esr/ciabot/ciabot.sh"
103 +version=3.4
104
105 # Addresses for the e-mail
81 -from="CIABOT-NOREPLY@${host}"
82 -to="cia@cia.navi.cx"
106 +from="CIABOT-NOREPLY@${hostname}"
107 +to="cia@cia.vc"
108
109 # SMTP client to use - may need to edit the absolute pathname for your system
110 sendmail="sendmail -t -f ${from}"
@@ -97,7 +122,7 @@ do
122 case $opt in
123 p) project=$2; shift ; shift ;;
124 n) mode=dumpit; shift ;;
100 - V) echo "ciabot.sh: version 3.2"; exit 0; shift ;;
125 + V) echo "ciabot.sh: version $version"; exit 0; shift ;;
126 esac
127 done
128
@@ -128,33 +153,29 @@ fi
153
154 refname=${refname##refs/heads/}
155
131 -gitver=$(git --version)
132 -gitver=${gitver##* }
156 +case $revformat in
157 +raw) rev=$merged ;;
158 +short) rev='' ;;
159 +*) rev=$(git describe ${merged} 2>/dev/null) ;;
160 +esac
161 +[ -z ${rev} ] && rev=$(echo "$merged" | cut -c 1-12)
162
134 -rev=$(git describe ${merged} 2>/dev/null)
135 -# ${merged:0:12} was the only bashism left in the 2008 version of this
136 -# script, according to checkbashisms. Replace it with ${merged} here
137 -# because it was just a fallback anyway, and it's worth accepting a
138 -# longer fallback for faster execution and removing the bash
139 -# dependency.
140 -[ -z ${rev} ] && rev=${merged}
141 -
142 -# This discards the part of the author's address after @.
163 +# We discard the part of the author's address after @.
164 # Might be nice to ship the full email address, if not
165 # for spammers' address harvesters - getting this wrong
166 # would make the freenode #commits channel into harvester heaven.
146 -rawcommit=$(git cat-file commit ${merged})
147 -author=$(echo "$rawcommit" | sed -n -e '/^author .*<\([^@]*\).*$/s--\1-p')
148 -logmessage=$(echo "$rawcommit" | sed -e '1,/^$/d' | head -n 1)
149 -logmessage=$(echo "$logmessage" | sed 's/\&/&amp\;/g; s/</&lt\;/g; s/>/&gt\;/g')
150 -ts=$(echo "$rawcommit" | sed -n -e '/^author .*> \([0-9]\+\).*$/s--\1-p')
167 +author=$(git log -1 '--pretty=format:%an <%ae>' $merged)
168 +author=$(echo "$author" | sed -n -e '/^.*<\([^@]*\).*$/s--\1-p')
169 +
170 +logmessage=$(git log -1 '--pretty=format:%s' $merged)
171 +ts=$(git log -1 '--pretty=format:%at' $merged)
172 files=$(git diff-tree -r --name-only ${merged} | sed -e '1d' -e 's-.*-<file>&</file>-')
173
174 out="
175 <message>
176 <generator>
177 <name>CIA Shell client for Git</name>
157 - <version>${gitver}</version>
178 + <version>${version}</version>
179 <url>${generator}</url>
180 </generator>
181 <source>