Mercurial > hg
annotate hgext/hgcia.py @ 14046:b24e5a708fad
web: Made elapsed time calculation dynamic (javascript).
This allow safe caching of the pages by the browser and still display the right
amount of elapsed time upon page refresh.
If javascript is disabled, absolute time is displayed, leaving it readable.
All the templates have been updated.
author | Benoit Allard <benoit@aeteurope.nl> |
---|---|
date | Thu, 28 Apr 2011 17:02:39 +0200 |
parents | a8d13ee0ce68 |
children | c322890b03e6 |
rev | line source |
---|---|
7438 | 1 # Copyright (C) 2007-8 Brendan Cully <brendan@kublai.com> |
10263 | 2 # |
3 # This software may be used and distributed according to the terms of the | |
4 # GNU General Public License version 2 or any later version. | |
7438 | 5 |
8935
f4f0e902b750
extensions: change descriptions for hook-providing extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
8894
diff
changeset
|
6 """hooks for integrating with the CIA.vc notification service |
7438 | 7 |
9260
b2f37dbc5952
hgcia: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents:
9208
diff
changeset
|
8 This is meant to be run as a changegroup or incoming hook. To |
b2f37dbc5952
hgcia: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents:
9208
diff
changeset
|
9 configure it, set the following options in your hgrc:: |
7438 | 10 |
9208
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
11 [cia] |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
12 # your registered CIA user name |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
13 user = foo |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
14 # the name of the project in CIA |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
15 project = foo |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
16 # the module (subproject) (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
17 #module = foo |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
18 # Append a diffstat to the log message (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
19 #diffstat = False |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
20 # Template to use for log messages (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
21 #template = {desc}\\n{baseurl}/rev/{node}-- {diffstat} |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
22 # Style to use (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
23 #style = foo |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
24 # The URL of the CIA notification service (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
25 # You can use mailto: URLs to send by email, eg |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
26 # mailto:cia@cia.vc |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
27 # Make sure to set email.from if you do this. |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
28 #url = http://cia.vc/ |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
29 # print message instead of sending it (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
30 #test = False |
7438 | 31 |
9208
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
32 [hooks] |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
33 # one of these: |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
34 changegroup.cia = python:hgcia.hook |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
35 #incoming.cia = python:hgcia.hook |
7438 | 36 |
9208
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
37 [web] |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
38 # If you want hyperlinks (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
39 baseurl = http://server/path/to/repo |
7438 | 40 """ |
41 | |
42 from mercurial.i18n import _ | |
11750
26e413f55b5e
hgcia/color: remove star imports
Brodie Rao <brodie@bitheap.org>
parents:
10611
diff
changeset
|
43 from mercurial.node import bin, short |
7438 | 44 from mercurial import cmdutil, patch, templater, util, mail |
45 import email.Parser | |
46 | |
47 import xmlrpclib | |
48 from xml.sax import saxutils | |
49 | |
50 socket_timeout = 30 # seconds | |
51 try: | |
52 # set a timeout for the socket so you don't have to wait so looooong | |
53 # when cia.vc is having problems. requires python >= 2.3: | |
54 import socket | |
55 socket.setdefaulttimeout(socket_timeout) | |
56 except: | |
57 pass | |
58 | |
59 HGCIA_VERSION = '0.1' | |
60 HGCIA_URL = 'http://hg.kublai.com/mercurial/hgcia' | |
61 | |
62 | |
63 class ciamsg(object): | |
64 """ A CIA message """ | |
65 def __init__(self, cia, ctx): | |
66 self.cia = cia | |
67 self.ctx = ctx | |
68 self.url = self.cia.url | |
69 | |
70 def fileelem(self, path, uri, action): | |
71 if uri: | |
72 uri = ' uri=%s' % saxutils.quoteattr(uri) | |
73 return '<file%s action=%s>%s</file>' % ( | |
74 uri, saxutils.quoteattr(action), saxutils.escape(path)) | |
75 | |
76 def fileelems(self): | |
77 n = self.ctx.node() | |
13878
a8d13ee0ce68
misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents:
13551
diff
changeset
|
78 f = self.cia.repo.status(self.ctx.p1().node(), n) |
7438 | 79 url = self.url or '' |
80 elems = [] | |
81 for path in f[0]: | |
82 uri = '%s/diff/%s/%s' % (url, short(n), path) | |
83 elems.append(self.fileelem(path, url and uri, 'modify')) | |
84 for path in f[1]: | |
85 # TODO: copy/rename ? | |
86 uri = '%s/file/%s/%s' % (url, short(n), path) | |
87 elems.append(self.fileelem(path, url and uri, 'add')) | |
88 for path in f[2]: | |
89 elems.append(self.fileelem(path, '', 'remove')) | |
90 | |
91 return '\n'.join(elems) | |
92 | |
93 def sourceelem(self, project, module=None, branch=None): | |
94 msg = ['<source>', '<project>%s</project>' % saxutils.escape(project)] | |
95 if module: | |
96 msg.append('<module>%s</module>' % saxutils.escape(module)) | |
97 if branch: | |
98 msg.append('<branch>%s</branch>' % saxutils.escape(branch)) | |
99 msg.append('</source>') | |
100 | |
101 return '\n'.join(msg) | |
102 | |
103 def diffstat(self): | |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8541
diff
changeset
|
104 class patchbuf(object): |
7438 | 105 def __init__(self): |
106 self.lines = [] | |
107 # diffstat is stupid | |
108 self.name = 'cia' | |
109 def write(self, data): | |
110 self.lines.append(data) | |
111 def close(self): | |
112 pass | |
113 | |
114 n = self.ctx.node() | |
115 pbuf = patchbuf() | |
10611
e764f24a45ee
patch/diff: move patch.export() to cmdutil.export()
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10529
diff
changeset
|
116 cmdutil.export(self.cia.repo, [n], fp=pbuf) |
7438 | 117 return patch.diffstat(pbuf.lines) or '' |
118 | |
119 def logmsg(self): | |
120 diffstat = self.cia.diffstat and self.diffstat() or '' | |
121 self.cia.ui.pushbuffer() | |
122 self.cia.templater.show(self.ctx, changes=self.ctx.changeset(), | |
123 url=self.cia.url, diffstat=diffstat) | |
124 return self.cia.ui.popbuffer() | |
125 | |
126 def xml(self): | |
127 n = short(self.ctx.node()) | |
128 src = self.sourceelem(self.cia.project, module=self.cia.module, | |
129 branch=self.ctx.branch()) | |
130 # unix timestamp | |
131 dt = self.ctx.date() | |
132 timestamp = dt[0] | |
133 | |
134 author = saxutils.escape(self.ctx.user()) | |
135 rev = '%d:%s' % (self.ctx.rev(), n) | |
136 log = saxutils.escape(self.logmsg()) | |
137 | |
138 url = self.url and '<url>%s/rev/%s</url>' % (saxutils.escape(self.url), | |
139 n) or '' | |
140 | |
141 msg = """ | |
142 <message> | |
143 <generator> | |
144 <name>Mercurial (hgcia)</name> | |
145 <version>%s</version> | |
146 <url>%s</url> | |
147 <user>%s</user> | |
148 </generator> | |
149 %s | |
150 <body> | |
151 <commit> | |
152 <author>%s</author> | |
153 <version>%s</version> | |
154 <log>%s</log> | |
155 %s | |
156 <files>%s</files> | |
157 </commit> | |
158 </body> | |
159 <timestamp>%d</timestamp> | |
160 </message> | |
161 """ % \ | |
162 (HGCIA_VERSION, saxutils.escape(HGCIA_URL), | |
163 saxutils.escape(self.cia.user), src, author, rev, log, url, | |
164 self.fileelems(), timestamp) | |
165 | |
166 return msg | |
167 | |
168 | |
169 class hgcia(object): | |
170 """ CIA notification class """ | |
171 | |
172 deftemplate = '{desc}' | |
173 dstemplate = '{desc}\n-- \n{diffstat}' | |
174 | |
175 def __init__(self, ui, repo): | |
176 self.ui = ui | |
177 self.repo = repo | |
178 | |
179 self.ciaurl = self.ui.config('cia', 'url', 'http://cia.vc') | |
180 self.user = self.ui.config('cia', 'user') | |
181 self.project = self.ui.config('cia', 'project') | |
182 self.module = self.ui.config('cia', 'module') | |
183 self.diffstat = self.ui.configbool('cia', 'diffstat') | |
184 self.emailfrom = self.ui.config('email', 'from') | |
185 self.dryrun = self.ui.configbool('cia', 'test') | |
186 self.url = self.ui.config('web', 'baseurl') | |
187 | |
188 style = self.ui.config('cia', 'style') | |
189 template = self.ui.config('cia', 'template') | |
190 if not template: | |
191 template = self.diffstat and self.dstemplate or self.deftemplate | |
192 template = templater.parsestring(template, quoted=False) | |
7762
fece056bf240
add --git option to commands supporting --patch (log, incoming, history, tip)
Jim Correia <jim.correia@pobox.com>
parents:
7438
diff
changeset
|
193 t = cmdutil.changeset_templater(self.ui, self.repo, False, None, |
fece056bf240
add --git option to commands supporting --patch (log, incoming, history, tip)
Jim Correia <jim.correia@pobox.com>
parents:
7438
diff
changeset
|
194 style, False) |
7438 | 195 t.use_template(template) |
196 self.templater = t | |
197 | |
198 def sendrpc(self, msg): | |
199 srv = xmlrpclib.Server(self.ciaurl) | |
10529
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
200 res = srv.hub.deliver(msg) |
13551
bbfae32f178e
hgcia: accept "queued." xmlrpc return as success
Georg Brandl <georg@python.org>
parents:
11750
diff
changeset
|
201 if res is not True and res != 'queued.': |
10529
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
202 raise util.Abort(_('%s returned an error: %s') % |
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
203 (self.ciaurl, res)) |
7438 | 204 |
205 def sendemail(self, address, data): | |
206 p = email.Parser.Parser() | |
207 msg = p.parsestr(data) | |
208 msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2") | |
209 msg['To'] = address | |
210 msg['From'] = self.emailfrom | |
211 msg['Subject'] = 'DeliverXML' | |
212 msg['Content-type'] = 'text/xml' | |
9136
31177742f54a
for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
9062
diff
changeset
|
213 msgtext = msg.as_string() |
7438 | 214 |
215 self.ui.status(_('hgcia: sending update to %s\n') % address) | |
216 mail.sendmail(self.ui, util.email(self.emailfrom), | |
217 [address], msgtext) | |
218 | |
219 | |
220 def hook(ui, repo, hooktype, node=None, url=None, **kwargs): | |
221 """ send CIA notification """ | |
222 def sendmsg(cia, ctx): | |
223 msg = ciamsg(cia, ctx).xml() | |
224 if cia.dryrun: | |
225 ui.write(msg) | |
226 elif cia.ciaurl.startswith('mailto:'): | |
227 if not cia.emailfrom: | |
228 raise util.Abort(_('email.from must be defined when ' | |
229 'sending by email')) | |
230 cia.sendemail(cia.ciaurl[7:], msg) | |
231 else: | |
232 cia.sendrpc(msg) | |
233 | |
234 n = bin(node) | |
235 cia = hgcia(ui, repo) | |
236 if not cia.user: | |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9260
diff
changeset
|
237 ui.debug('cia: no user specified') |
7438 | 238 return |
239 if not cia.project: | |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9260
diff
changeset
|
240 ui.debug('cia: no project specified') |
7438 | 241 return |
242 if hooktype == 'changegroup': | |
243 start = repo.changelog.rev(n) | |
244 end = len(repo.changelog) | |
245 for rev in xrange(start, end): | |
246 n = repo.changelog.node(rev) | |
247 ctx = repo.changectx(n) | |
248 sendmsg(cia, ctx) | |
249 else: | |
250 ctx = repo.changectx(n) | |
251 sendmsg(cia, ctx) |