11
11
#
12
12
# This script is meant to be run either in a post-commit hook or in an
13
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
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
22
#
23
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
25
# from most recent to oldest.
26
26
#
27
27
# /path/to/ciabot.py ${refname} $(git rev-list ${oldhead}..${newhead} | tac)
28
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
31
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
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'.
39
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.
41
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 ())
47
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
51
49
52
50
# Changeset URL prefix for your repo: when the commit ID is appended
53
51
# to this, it should point at a CGI that will display the commit
72
70
<message>
73
71
<generator>
74
72
<name>CIA Python client for Git</name>
75
- <version>%(gitver )s</version>
73
+ <version>%(version )s</version>
76
74
<url>%(generator)s</url>
77
75
</generator>
78
76
<source>
98
96
# No user-serviceable parts below this line:
99
97
#
100
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
-
99
+ # Where to ship e-mail notifications.
100
+
105
101
106
102
# Identify the generator script.
107
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"
109
106
110
107
def do (command ):
111
108
return commands .getstatusoutput (command )[1 ]
112
109
113
- def report (refname , merged ):
110
+ def report (refname , merged , xmlrpc = True ):
114
111
"Generate a commit notification to be reported to CIA"
115
112
116
113
# Try to tinyfy a reference to a web view for this commit.
@@ -121,32 +118,27 @@ def report(refname, merged):
121
118
122
119
branch = os .path .basename (refname )
123
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
129
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 )
144
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
147
139
# for spammers' address harvesters - getting this wrong
148
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 ])
150
142
151
143
# This ignores the timezone. Not clear what to do with it...
152
144
ts = ts .strip ().split ()[0 ]
@@ -155,8 +147,7 @@ def report(refname, merged):
155
147
context .update (globals ())
156
148
157
149
out = xml % context
158
-
159
- message = '''\
150
+ mail = '''\
160
151
Message-ID: <%(merged)s.%(author)s@%(project)s>
161
152
From: %(fromaddr)s
162
153
To: %(toaddr)s
@@ -165,34 +156,49 @@ def report(refname, merged):
165
156
166
157
%(out)s''' % locals ()
167
158
168
- return message
159
+ if xmlrpc :
160
+ return out
161
+ else :
162
+ return mail
169
163
170
164
if __name__ == "__main__" :
171
165
import getopt
172
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
+
173
177
try :
174
- (options , arguments ) = getopt .getopt (sys .argv [1 :], "np:V " )
178
+ (options , arguments ) = getopt .getopt (sys .argv [1 :], "np:xV " )
175
179
except getopt .GetoptError , msg :
176
180
print "ciabot.py: " + str (msg )
177
181
raise SystemExit , 1
178
182
179
- mailit = True
183
+ notify = True
180
184
for (switch , val ) in options :
181
185
if switch == '-p' :
182
186
project = val
183
187
elif switch == '-n' :
184
- mailit = False
188
+ notify = False
189
+ elif switch == '-x' :
190
+ xmlrpc = True
185
191
elif switch == '-V' :
186
- print "ciabot.py: version 3.2"
192
+ print "ciabot.py: version" , version
187
193
sys .exit (0 )
188
194
189
195
# Cough and die if user has not specified a project
190
196
if not project :
191
197
sys .stderr .write ("ciabot.py: no project specified, bailing out.\n " )
192
198
sys .exit (1 )
193
199
194
- # We'll need the git version number.
195
- gitver = do ( "git --version" ). split ()[ 0 ]
200
+ if not repo :
201
+ repo = project . lower ()
196
202
197
203
urlprefix = urlprefix % globals ()
198
204
@@ -205,18 +211,29 @@ def report(refname, merged):
205
211
refname = arguments [0 ]
206
212
merges = arguments [1 :]
207
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' )
211
221
212
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 :
217
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 )
218
234
219
- if mailit :
220
- server .quit ()
235
+ if notify :
236
+ if not xmlrpc :
237
+ server .quit ()
221
238
222
239
#End
0 commit comments