Mercurial > hg
annotate hgext/hgcia.py @ 14425:e89534504fb9
record: add an option to backup all wc modifications
Also, don't create a backup dir if we have no files to backup.
This is essential for qrefresh --interactive. Since we can't
select individual files to qrefresh without eliminating already
present changes, we have to backup all changes in the working
copy to avoid refreshing unaccepted hunks.
(thanks to Patrick for the idea)
author | Idan Kamara <idankk86@gmail.com> |
---|---|
date | Tue, 24 May 2011 19:17:04 +0300 |
parents | c322890b03e6 |
children | a95242af945c |
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) |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
21 #template = {desc}\\n{baseurl}{webroot}/rev/{node}-- {diffstat} |
9208
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 |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
31 # number of slashes to strip for url paths |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
32 #strip = 0 |
7438 | 33 |
9208
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
34 [hooks] |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
35 # one of these: |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
36 changegroup.cia = python:hgcia.hook |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
37 #incoming.cia = python:hgcia.hook |
7438 | 38 |
9208
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
39 [web] |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
40 # If you want hyperlinks (optional) |
12d119ae39bc
hgcia: use reST syntax for literal block
Martin Geisler <mg@lazybytes.net>
parents:
9136
diff
changeset
|
41 baseurl = http://server/path/to/repo |
7438 | 42 """ |
43 | |
44 from mercurial.i18n import _ | |
11750
26e413f55b5e
hgcia/color: remove star imports
Brodie Rao <brodie@bitheap.org>
parents:
10611
diff
changeset
|
45 from mercurial.node import bin, short |
7438 | 46 from mercurial import cmdutil, patch, templater, util, mail |
47 import email.Parser | |
48 | |
49 import xmlrpclib | |
50 from xml.sax import saxutils | |
51 | |
52 socket_timeout = 30 # seconds | |
53 try: | |
54 # set a timeout for the socket so you don't have to wait so looooong | |
55 # when cia.vc is having problems. requires python >= 2.3: | |
56 import socket | |
57 socket.setdefaulttimeout(socket_timeout) | |
58 except: | |
59 pass | |
60 | |
61 HGCIA_VERSION = '0.1' | |
62 HGCIA_URL = 'http://hg.kublai.com/mercurial/hgcia' | |
63 | |
64 | |
65 class ciamsg(object): | |
66 """ A CIA message """ | |
67 def __init__(self, cia, ctx): | |
68 self.cia = cia | |
69 self.ctx = ctx | |
70 self.url = self.cia.url | |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
71 if self.url: |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
72 self.url += self.cia.root |
7438 | 73 |
74 def fileelem(self, path, uri, action): | |
75 if uri: | |
76 uri = ' uri=%s' % saxutils.quoteattr(uri) | |
77 return '<file%s action=%s>%s</file>' % ( | |
78 uri, saxutils.quoteattr(action), saxutils.escape(path)) | |
79 | |
80 def fileelems(self): | |
81 n = self.ctx.node() | |
13878
a8d13ee0ce68
misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents:
13551
diff
changeset
|
82 f = self.cia.repo.status(self.ctx.p1().node(), n) |
7438 | 83 url = self.url or '' |
84 elems = [] | |
85 for path in f[0]: | |
86 uri = '%s/diff/%s/%s' % (url, short(n), path) | |
87 elems.append(self.fileelem(path, url and uri, 'modify')) | |
88 for path in f[1]: | |
89 # TODO: copy/rename ? | |
90 uri = '%s/file/%s/%s' % (url, short(n), path) | |
91 elems.append(self.fileelem(path, url and uri, 'add')) | |
92 for path in f[2]: | |
93 elems.append(self.fileelem(path, '', 'remove')) | |
94 | |
95 return '\n'.join(elems) | |
96 | |
97 def sourceelem(self, project, module=None, branch=None): | |
98 msg = ['<source>', '<project>%s</project>' % saxutils.escape(project)] | |
99 if module: | |
100 msg.append('<module>%s</module>' % saxutils.escape(module)) | |
101 if branch: | |
102 msg.append('<branch>%s</branch>' % saxutils.escape(branch)) | |
103 msg.append('</source>') | |
104 | |
105 return '\n'.join(msg) | |
106 | |
107 def diffstat(self): | |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8541
diff
changeset
|
108 class patchbuf(object): |
7438 | 109 def __init__(self): |
110 self.lines = [] | |
111 # diffstat is stupid | |
112 self.name = 'cia' | |
113 def write(self, data): | |
114 self.lines.append(data) | |
115 def close(self): | |
116 pass | |
117 | |
118 n = self.ctx.node() | |
119 pbuf = patchbuf() | |
10611
e764f24a45ee
patch/diff: move patch.export() to cmdutil.export()
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10529
diff
changeset
|
120 cmdutil.export(self.cia.repo, [n], fp=pbuf) |
7438 | 121 return patch.diffstat(pbuf.lines) or '' |
122 | |
123 def logmsg(self): | |
124 diffstat = self.cia.diffstat and self.diffstat() or '' | |
125 self.cia.ui.pushbuffer() | |
126 self.cia.templater.show(self.ctx, changes=self.ctx.changeset(), | |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
127 baseurl=self.cia.ui.config('web', 'baseurl'), |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
128 url=self.url, diffstat=diffstat, |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
129 webroot=self.cia.root) |
7438 | 130 return self.cia.ui.popbuffer() |
131 | |
132 def xml(self): | |
133 n = short(self.ctx.node()) | |
134 src = self.sourceelem(self.cia.project, module=self.cia.module, | |
135 branch=self.ctx.branch()) | |
136 # unix timestamp | |
137 dt = self.ctx.date() | |
138 timestamp = dt[0] | |
139 | |
140 author = saxutils.escape(self.ctx.user()) | |
141 rev = '%d:%s' % (self.ctx.rev(), n) | |
142 log = saxutils.escape(self.logmsg()) | |
143 | |
144 url = self.url and '<url>%s/rev/%s</url>' % (saxutils.escape(self.url), | |
145 n) or '' | |
146 | |
147 msg = """ | |
148 <message> | |
149 <generator> | |
150 <name>Mercurial (hgcia)</name> | |
151 <version>%s</version> | |
152 <url>%s</url> | |
153 <user>%s</user> | |
154 </generator> | |
155 %s | |
156 <body> | |
157 <commit> | |
158 <author>%s</author> | |
159 <version>%s</version> | |
160 <log>%s</log> | |
161 %s | |
162 <files>%s</files> | |
163 </commit> | |
164 </body> | |
165 <timestamp>%d</timestamp> | |
166 </message> | |
167 """ % \ | |
168 (HGCIA_VERSION, saxutils.escape(HGCIA_URL), | |
169 saxutils.escape(self.cia.user), src, author, rev, log, url, | |
170 self.fileelems(), timestamp) | |
171 | |
172 return msg | |
173 | |
174 | |
175 class hgcia(object): | |
176 """ CIA notification class """ | |
177 | |
178 deftemplate = '{desc}' | |
179 dstemplate = '{desc}\n-- \n{diffstat}' | |
180 | |
181 def __init__(self, ui, repo): | |
182 self.ui = ui | |
183 self.repo = repo | |
184 | |
185 self.ciaurl = self.ui.config('cia', 'url', 'http://cia.vc') | |
186 self.user = self.ui.config('cia', 'user') | |
187 self.project = self.ui.config('cia', 'project') | |
188 self.module = self.ui.config('cia', 'module') | |
189 self.diffstat = self.ui.configbool('cia', 'diffstat') | |
190 self.emailfrom = self.ui.config('email', 'from') | |
191 self.dryrun = self.ui.configbool('cia', 'test') | |
192 self.url = self.ui.config('web', 'baseurl') | |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
193 self.stripcount = int(self.ui.config('cia', 'strip', 0)) |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
194 self.root = self.strip(self.repo.root) |
7438 | 195 |
196 style = self.ui.config('cia', 'style') | |
197 template = self.ui.config('cia', 'template') | |
198 if not template: | |
199 template = self.diffstat and self.dstemplate or self.deftemplate | |
200 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
|
201 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
|
202 style, False) |
7438 | 203 t.use_template(template) |
204 self.templater = t | |
205 | |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
206 def strip(self, path): |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
207 '''strip leading slashes from local path, turn into web-safe path.''' |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
208 |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
209 path = util.pconvert(path) |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
210 count = self.stripcount |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
211 while count > 0: |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
212 c = path.find('/') |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
213 if c == -1: |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
214 break |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
215 path = path[c + 1:] |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
216 count -= 1 |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
217 return path |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
218 |
7438 | 219 def sendrpc(self, msg): |
220 srv = xmlrpclib.Server(self.ciaurl) | |
10529
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
221 res = srv.hub.deliver(msg) |
13551
bbfae32f178e
hgcia: accept "queued." xmlrpc return as success
Georg Brandl <georg@python.org>
parents:
11750
diff
changeset
|
222 if res is not True and res != 'queued.': |
10529
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
223 raise util.Abort(_('%s returned an error: %s') % |
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
224 (self.ciaurl, res)) |
7438 | 225 |
226 def sendemail(self, address, data): | |
227 p = email.Parser.Parser() | |
228 msg = p.parsestr(data) | |
229 msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2") | |
230 msg['To'] = address | |
231 msg['From'] = self.emailfrom | |
232 msg['Subject'] = 'DeliverXML' | |
233 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
|
234 msgtext = msg.as_string() |
7438 | 235 |
236 self.ui.status(_('hgcia: sending update to %s\n') % address) | |
237 mail.sendmail(self.ui, util.email(self.emailfrom), | |
238 [address], msgtext) | |
239 | |
240 | |
241 def hook(ui, repo, hooktype, node=None, url=None, **kwargs): | |
242 """ send CIA notification """ | |
243 def sendmsg(cia, ctx): | |
244 msg = ciamsg(cia, ctx).xml() | |
245 if cia.dryrun: | |
246 ui.write(msg) | |
247 elif cia.ciaurl.startswith('mailto:'): | |
248 if not cia.emailfrom: | |
249 raise util.Abort(_('email.from must be defined when ' | |
250 'sending by email')) | |
251 cia.sendemail(cia.ciaurl[7:], msg) | |
252 else: | |
253 cia.sendrpc(msg) | |
254 | |
255 n = bin(node) | |
256 cia = hgcia(ui, repo) | |
257 if not cia.user: | |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9260
diff
changeset
|
258 ui.debug('cia: no user specified') |
7438 | 259 return |
260 if not cia.project: | |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9260
diff
changeset
|
261 ui.debug('cia: no project specified') |
7438 | 262 return |
263 if hooktype == 'changegroup': | |
264 start = repo.changelog.rev(n) | |
265 end = len(repo.changelog) | |
266 for rev in xrange(start, end): | |
267 n = repo.changelog.node(rev) | |
268 ctx = repo.changectx(n) | |
269 sendmsg(cia, ctx) | |
270 else: | |
271 ctx = repo.changectx(n) | |
272 sendmsg(cia, ctx) |