Mercurial > hg
annotate hgext/hgcia.py @ 9021:2ccb527c7b1a
gendoc: fix localization of help topic
When a topic provides a callable method for its text, most likely
this text will be generated from different parts, so it does not
make sense to apply gettext on the whole result, rather the method
should provide translation by itself.
This is the case with the extensions topic, which triggers a double
gettext call, making the ASCII codec fail when it encounters 8 bit
characters, and prevents the documentation from being built.
author | Cédric Duval <cedricduval@free.fr> |
---|---|
date | Sat, 04 Jul 2009 12:12:36 +0200 |
parents | f4f0e902b750 |
children | 6921a7140ab3 |
rev | line source |
---|---|
7438 | 1 # Copyright (C) 2007-8 Brendan Cully <brendan@kublai.com> |
2 # Published under the GNU GPL | |
3 | |
8935
f4f0e902b750
extensions: change descriptions for hook-providing extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
8894
diff
changeset
|
4 """hooks for integrating with the CIA.vc notification service |
7438 | 5 |
6 This is meant to be run as a changegroup or incoming hook. | |
7 To configure it, set the following options in your hgrc: | |
8 | |
9 [cia] | |
10 # your registered CIA user name | |
11 user = foo | |
12 # the name of the project in CIA | |
13 project = foo | |
14 # the module (subproject) (optional) | |
15 #module = foo | |
16 # Append a diffstat to the log message (optional) | |
17 #diffstat = False | |
18 # Template to use for log messages (optional) | |
8541
06ace50443f6
hgcia, convert: escape backslashes in docstrings
Martin Geisler <mg@lazybytes.net>
parents:
7762
diff
changeset
|
19 #template = {desc}\\n{baseurl}/rev/{node}-- {diffstat} |
7438 | 20 # Style to use (optional) |
21 #style = foo | |
22 # The URL of the CIA notification service (optional) | |
23 # You can use mailto: URLs to send by email, eg | |
24 # mailto:cia@cia.vc | |
25 # Make sure to set email.from if you do this. | |
26 #url = http://cia.vc/ | |
27 # print message instead of sending it (optional) | |
28 #test = False | |
29 | |
30 [hooks] | |
31 # one of these: | |
32 changegroup.cia = python:hgcia.hook | |
33 #incoming.cia = python:hgcia.hook | |
34 | |
35 [web] | |
36 # If you want hyperlinks (optional) | |
37 baseurl = http://server/path/to/repo | |
38 """ | |
39 | |
40 from mercurial.i18n import _ | |
41 from mercurial.node import * | |
42 from mercurial import cmdutil, patch, templater, util, mail | |
43 import email.Parser | |
44 | |
45 import xmlrpclib | |
46 from xml.sax import saxutils | |
47 | |
48 socket_timeout = 30 # seconds | |
49 try: | |
50 # set a timeout for the socket so you don't have to wait so looooong | |
51 # when cia.vc is having problems. requires python >= 2.3: | |
52 import socket | |
53 socket.setdefaulttimeout(socket_timeout) | |
54 except: | |
55 pass | |
56 | |
57 HGCIA_VERSION = '0.1' | |
58 HGCIA_URL = 'http://hg.kublai.com/mercurial/hgcia' | |
59 | |
60 | |
61 class ciamsg(object): | |
62 """ A CIA message """ | |
63 def __init__(self, cia, ctx): | |
64 self.cia = cia | |
65 self.ctx = ctx | |
66 self.url = self.cia.url | |
67 | |
68 def fileelem(self, path, uri, action): | |
69 if uri: | |
70 uri = ' uri=%s' % saxutils.quoteattr(uri) | |
71 return '<file%s action=%s>%s</file>' % ( | |
72 uri, saxutils.quoteattr(action), saxutils.escape(path)) | |
73 | |
74 def fileelems(self): | |
75 n = self.ctx.node() | |
76 f = self.cia.repo.status(self.ctx.parents()[0].node(), n) | |
77 url = self.url or '' | |
78 elems = [] | |
79 for path in f[0]: | |
80 uri = '%s/diff/%s/%s' % (url, short(n), path) | |
81 elems.append(self.fileelem(path, url and uri, 'modify')) | |
82 for path in f[1]: | |
83 # TODO: copy/rename ? | |
84 uri = '%s/file/%s/%s' % (url, short(n), path) | |
85 elems.append(self.fileelem(path, url and uri, 'add')) | |
86 for path in f[2]: | |
87 elems.append(self.fileelem(path, '', 'remove')) | |
88 | |
89 return '\n'.join(elems) | |
90 | |
91 def sourceelem(self, project, module=None, branch=None): | |
92 msg = ['<source>', '<project>%s</project>' % saxutils.escape(project)] | |
93 if module: | |
94 msg.append('<module>%s</module>' % saxutils.escape(module)) | |
95 if branch: | |
96 msg.append('<branch>%s</branch>' % saxutils.escape(branch)) | |
97 msg.append('</source>') | |
98 | |
99 return '\n'.join(msg) | |
100 | |
101 def diffstat(self): | |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8541
diff
changeset
|
102 class patchbuf(object): |
7438 | 103 def __init__(self): |
104 self.lines = [] | |
105 # diffstat is stupid | |
106 self.name = 'cia' | |
107 def write(self, data): | |
108 self.lines.append(data) | |
109 def close(self): | |
110 pass | |
111 | |
112 n = self.ctx.node() | |
113 pbuf = patchbuf() | |
114 patch.export(self.cia.repo, [n], fp=pbuf) | |
115 return patch.diffstat(pbuf.lines) or '' | |
116 | |
117 def logmsg(self): | |
118 diffstat = self.cia.diffstat and self.diffstat() or '' | |
119 self.cia.ui.pushbuffer() | |
120 self.cia.templater.show(self.ctx, changes=self.ctx.changeset(), | |
121 url=self.cia.url, diffstat=diffstat) | |
122 return self.cia.ui.popbuffer() | |
123 | |
124 def xml(self): | |
125 n = short(self.ctx.node()) | |
126 src = self.sourceelem(self.cia.project, module=self.cia.module, | |
127 branch=self.ctx.branch()) | |
128 # unix timestamp | |
129 dt = self.ctx.date() | |
130 timestamp = dt[0] | |
131 | |
132 author = saxutils.escape(self.ctx.user()) | |
133 rev = '%d:%s' % (self.ctx.rev(), n) | |
134 log = saxutils.escape(self.logmsg()) | |
135 | |
136 url = self.url and '<url>%s/rev/%s</url>' % (saxutils.escape(self.url), | |
137 n) or '' | |
138 | |
139 msg = """ | |
140 <message> | |
141 <generator> | |
142 <name>Mercurial (hgcia)</name> | |
143 <version>%s</version> | |
144 <url>%s</url> | |
145 <user>%s</user> | |
146 </generator> | |
147 %s | |
148 <body> | |
149 <commit> | |
150 <author>%s</author> | |
151 <version>%s</version> | |
152 <log>%s</log> | |
153 %s | |
154 <files>%s</files> | |
155 </commit> | |
156 </body> | |
157 <timestamp>%d</timestamp> | |
158 </message> | |
159 """ % \ | |
160 (HGCIA_VERSION, saxutils.escape(HGCIA_URL), | |
161 saxutils.escape(self.cia.user), src, author, rev, log, url, | |
162 self.fileelems(), timestamp) | |
163 | |
164 return msg | |
165 | |
166 | |
167 class hgcia(object): | |
168 """ CIA notification class """ | |
169 | |
170 deftemplate = '{desc}' | |
171 dstemplate = '{desc}\n-- \n{diffstat}' | |
172 | |
173 def __init__(self, ui, repo): | |
174 self.ui = ui | |
175 self.repo = repo | |
176 | |
177 self.ciaurl = self.ui.config('cia', 'url', 'http://cia.vc') | |
178 self.user = self.ui.config('cia', 'user') | |
179 self.project = self.ui.config('cia', 'project') | |
180 self.module = self.ui.config('cia', 'module') | |
181 self.diffstat = self.ui.configbool('cia', 'diffstat') | |
182 self.emailfrom = self.ui.config('email', 'from') | |
183 self.dryrun = self.ui.configbool('cia', 'test') | |
184 self.url = self.ui.config('web', 'baseurl') | |
185 | |
186 style = self.ui.config('cia', 'style') | |
187 template = self.ui.config('cia', 'template') | |
188 if not template: | |
189 template = self.diffstat and self.dstemplate or self.deftemplate | |
190 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
|
191 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
|
192 style, False) |
7438 | 193 t.use_template(template) |
194 self.templater = t | |
195 | |
196 def sendrpc(self, msg): | |
197 srv = xmlrpclib.Server(self.ciaurl) | |
198 srv.hub.deliver(msg) | |
199 | |
200 def sendemail(self, address, data): | |
201 p = email.Parser.Parser() | |
202 msg = p.parsestr(data) | |
203 msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2") | |
204 msg['To'] = address | |
205 msg['From'] = self.emailfrom | |
206 msg['Subject'] = 'DeliverXML' | |
207 msg['Content-type'] = 'text/xml' | |
208 msgtext = msg.as_string(0) | |
209 | |
210 self.ui.status(_('hgcia: sending update to %s\n') % address) | |
211 mail.sendmail(self.ui, util.email(self.emailfrom), | |
212 [address], msgtext) | |
213 | |
214 | |
215 def hook(ui, repo, hooktype, node=None, url=None, **kwargs): | |
216 """ send CIA notification """ | |
217 def sendmsg(cia, ctx): | |
218 msg = ciamsg(cia, ctx).xml() | |
219 if cia.dryrun: | |
220 ui.write(msg) | |
221 elif cia.ciaurl.startswith('mailto:'): | |
222 if not cia.emailfrom: | |
223 raise util.Abort(_('email.from must be defined when ' | |
224 'sending by email')) | |
225 cia.sendemail(cia.ciaurl[7:], msg) | |
226 else: | |
227 cia.sendrpc(msg) | |
228 | |
229 n = bin(node) | |
230 cia = hgcia(ui, repo) | |
231 if not cia.user: | |
232 ui.debug(_('cia: no user specified')) | |
233 return | |
234 if not cia.project: | |
235 ui.debug(_('cia: no project specified')) | |
236 return | |
237 if hooktype == 'changegroup': | |
238 start = repo.changelog.rev(n) | |
239 end = len(repo.changelog) | |
240 for rev in xrange(start, end): | |
241 n = repo.changelog.node(rev) | |
242 ctx = repo.changectx(n) | |
243 sendmsg(cia, ctx) | |
244 else: | |
245 ctx = repo.changectx(n) | |
246 sendmsg(cia, ctx) |