##// END OF EJS Templates
hgcia: accept "queued." xmlrpc return as success
Georg Brandl -
r13551:bbfae32f stable
parent child Browse files
Show More
@@ -1,251 +1,251 b''
1 1 # Copyright (C) 2007-8 Brendan Cully <brendan@kublai.com>
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5
6 6 """hooks for integrating with the CIA.vc notification service
7 7
8 8 This is meant to be run as a changegroup or incoming hook. To
9 9 configure it, set the following options in your hgrc::
10 10
11 11 [cia]
12 12 # your registered CIA user name
13 13 user = foo
14 14 # the name of the project in CIA
15 15 project = foo
16 16 # the module (subproject) (optional)
17 17 #module = foo
18 18 # Append a diffstat to the log message (optional)
19 19 #diffstat = False
20 20 # Template to use for log messages (optional)
21 21 #template = {desc}\\n{baseurl}/rev/{node}-- {diffstat}
22 22 # Style to use (optional)
23 23 #style = foo
24 24 # The URL of the CIA notification service (optional)
25 25 # You can use mailto: URLs to send by email, eg
26 26 # mailto:cia@cia.vc
27 27 # Make sure to set email.from if you do this.
28 28 #url = http://cia.vc/
29 29 # print message instead of sending it (optional)
30 30 #test = False
31 31
32 32 [hooks]
33 33 # one of these:
34 34 changegroup.cia = python:hgcia.hook
35 35 #incoming.cia = python:hgcia.hook
36 36
37 37 [web]
38 38 # If you want hyperlinks (optional)
39 39 baseurl = http://server/path/to/repo
40 40 """
41 41
42 42 from mercurial.i18n import _
43 43 from mercurial.node import bin, short
44 44 from mercurial import cmdutil, patch, templater, util, mail
45 45 import email.Parser
46 46
47 47 import xmlrpclib
48 48 from xml.sax import saxutils
49 49
50 50 socket_timeout = 30 # seconds
51 51 try:
52 52 # set a timeout for the socket so you don't have to wait so looooong
53 53 # when cia.vc is having problems. requires python >= 2.3:
54 54 import socket
55 55 socket.setdefaulttimeout(socket_timeout)
56 56 except:
57 57 pass
58 58
59 59 HGCIA_VERSION = '0.1'
60 60 HGCIA_URL = 'http://hg.kublai.com/mercurial/hgcia'
61 61
62 62
63 63 class ciamsg(object):
64 64 """ A CIA message """
65 65 def __init__(self, cia, ctx):
66 66 self.cia = cia
67 67 self.ctx = ctx
68 68 self.url = self.cia.url
69 69
70 70 def fileelem(self, path, uri, action):
71 71 if uri:
72 72 uri = ' uri=%s' % saxutils.quoteattr(uri)
73 73 return '<file%s action=%s>%s</file>' % (
74 74 uri, saxutils.quoteattr(action), saxutils.escape(path))
75 75
76 76 def fileelems(self):
77 77 n = self.ctx.node()
78 78 f = self.cia.repo.status(self.ctx.parents()[0].node(), n)
79 79 url = self.url or ''
80 80 elems = []
81 81 for path in f[0]:
82 82 uri = '%s/diff/%s/%s' % (url, short(n), path)
83 83 elems.append(self.fileelem(path, url and uri, 'modify'))
84 84 for path in f[1]:
85 85 # TODO: copy/rename ?
86 86 uri = '%s/file/%s/%s' % (url, short(n), path)
87 87 elems.append(self.fileelem(path, url and uri, 'add'))
88 88 for path in f[2]:
89 89 elems.append(self.fileelem(path, '', 'remove'))
90 90
91 91 return '\n'.join(elems)
92 92
93 93 def sourceelem(self, project, module=None, branch=None):
94 94 msg = ['<source>', '<project>%s</project>' % saxutils.escape(project)]
95 95 if module:
96 96 msg.append('<module>%s</module>' % saxutils.escape(module))
97 97 if branch:
98 98 msg.append('<branch>%s</branch>' % saxutils.escape(branch))
99 99 msg.append('</source>')
100 100
101 101 return '\n'.join(msg)
102 102
103 103 def diffstat(self):
104 104 class patchbuf(object):
105 105 def __init__(self):
106 106 self.lines = []
107 107 # diffstat is stupid
108 108 self.name = 'cia'
109 109 def write(self, data):
110 110 self.lines.append(data)
111 111 def close(self):
112 112 pass
113 113
114 114 n = self.ctx.node()
115 115 pbuf = patchbuf()
116 116 cmdutil.export(self.cia.repo, [n], fp=pbuf)
117 117 return patch.diffstat(pbuf.lines) or ''
118 118
119 119 def logmsg(self):
120 120 diffstat = self.cia.diffstat and self.diffstat() or ''
121 121 self.cia.ui.pushbuffer()
122 122 self.cia.templater.show(self.ctx, changes=self.ctx.changeset(),
123 123 url=self.cia.url, diffstat=diffstat)
124 124 return self.cia.ui.popbuffer()
125 125
126 126 def xml(self):
127 127 n = short(self.ctx.node())
128 128 src = self.sourceelem(self.cia.project, module=self.cia.module,
129 129 branch=self.ctx.branch())
130 130 # unix timestamp
131 131 dt = self.ctx.date()
132 132 timestamp = dt[0]
133 133
134 134 author = saxutils.escape(self.ctx.user())
135 135 rev = '%d:%s' % (self.ctx.rev(), n)
136 136 log = saxutils.escape(self.logmsg())
137 137
138 138 url = self.url and '<url>%s/rev/%s</url>' % (saxutils.escape(self.url),
139 139 n) or ''
140 140
141 141 msg = """
142 142 <message>
143 143 <generator>
144 144 <name>Mercurial (hgcia)</name>
145 145 <version>%s</version>
146 146 <url>%s</url>
147 147 <user>%s</user>
148 148 </generator>
149 149 %s
150 150 <body>
151 151 <commit>
152 152 <author>%s</author>
153 153 <version>%s</version>
154 154 <log>%s</log>
155 155 %s
156 156 <files>%s</files>
157 157 </commit>
158 158 </body>
159 159 <timestamp>%d</timestamp>
160 160 </message>
161 161 """ % \
162 162 (HGCIA_VERSION, saxutils.escape(HGCIA_URL),
163 163 saxutils.escape(self.cia.user), src, author, rev, log, url,
164 164 self.fileelems(), timestamp)
165 165
166 166 return msg
167 167
168 168
169 169 class hgcia(object):
170 170 """ CIA notification class """
171 171
172 172 deftemplate = '{desc}'
173 173 dstemplate = '{desc}\n-- \n{diffstat}'
174 174
175 175 def __init__(self, ui, repo):
176 176 self.ui = ui
177 177 self.repo = repo
178 178
179 179 self.ciaurl = self.ui.config('cia', 'url', 'http://cia.vc')
180 180 self.user = self.ui.config('cia', 'user')
181 181 self.project = self.ui.config('cia', 'project')
182 182 self.module = self.ui.config('cia', 'module')
183 183 self.diffstat = self.ui.configbool('cia', 'diffstat')
184 184 self.emailfrom = self.ui.config('email', 'from')
185 185 self.dryrun = self.ui.configbool('cia', 'test')
186 186 self.url = self.ui.config('web', 'baseurl')
187 187
188 188 style = self.ui.config('cia', 'style')
189 189 template = self.ui.config('cia', 'template')
190 190 if not template:
191 191 template = self.diffstat and self.dstemplate or self.deftemplate
192 192 template = templater.parsestring(template, quoted=False)
193 193 t = cmdutil.changeset_templater(self.ui, self.repo, False, None,
194 194 style, False)
195 195 t.use_template(template)
196 196 self.templater = t
197 197
198 198 def sendrpc(self, msg):
199 199 srv = xmlrpclib.Server(self.ciaurl)
200 200 res = srv.hub.deliver(msg)
201 if res is not True:
201 if res is not True and res != 'queued.':
202 202 raise util.Abort(_('%s returned an error: %s') %
203 203 (self.ciaurl, res))
204 204
205 205 def sendemail(self, address, data):
206 206 p = email.Parser.Parser()
207 207 msg = p.parsestr(data)
208 208 msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2")
209 209 msg['To'] = address
210 210 msg['From'] = self.emailfrom
211 211 msg['Subject'] = 'DeliverXML'
212 212 msg['Content-type'] = 'text/xml'
213 213 msgtext = msg.as_string()
214 214
215 215 self.ui.status(_('hgcia: sending update to %s\n') % address)
216 216 mail.sendmail(self.ui, util.email(self.emailfrom),
217 217 [address], msgtext)
218 218
219 219
220 220 def hook(ui, repo, hooktype, node=None, url=None, **kwargs):
221 221 """ send CIA notification """
222 222 def sendmsg(cia, ctx):
223 223 msg = ciamsg(cia, ctx).xml()
224 224 if cia.dryrun:
225 225 ui.write(msg)
226 226 elif cia.ciaurl.startswith('mailto:'):
227 227 if not cia.emailfrom:
228 228 raise util.Abort(_('email.from must be defined when '
229 229 'sending by email'))
230 230 cia.sendemail(cia.ciaurl[7:], msg)
231 231 else:
232 232 cia.sendrpc(msg)
233 233
234 234 n = bin(node)
235 235 cia = hgcia(ui, repo)
236 236 if not cia.user:
237 237 ui.debug('cia: no user specified')
238 238 return
239 239 if not cia.project:
240 240 ui.debug('cia: no project specified')
241 241 return
242 242 if hooktype == 'changegroup':
243 243 start = repo.changelog.rev(n)
244 244 end = len(repo.changelog)
245 245 for rev in xrange(start, end):
246 246 n = repo.changelog.node(rev)
247 247 ctx = repo.changectx(n)
248 248 sendmsg(cia, ctx)
249 249 else:
250 250 ctx = repo.changectx(n)
251 251 sendmsg(cia, ctx)
General Comments 0
You need to be logged in to leave comments. Login now