Mercurial > hg-stable
annotate hgext/hgcia.py @ 15474:95174c381525
forget: support forgetting explicit paths in subrepos
Change the behavior of the forget command such that explicit paths in
subrepos are handled by forgetting the file in the subrepo. This eliminates the
previous behavior where if you called "hg forget" for an explicit path in a
subrepo, it would state that the file is already untracked.
author | David M. Carr <david@carrclan.us> |
---|---|
date | Wed, 09 Nov 2011 19:46:51 -0500 |
parents | a95242af945c |
children | 55a85a55f020 |
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 '' |
14850
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
84 if url and url[-1] == '/': |
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
85 url = url[:-1] |
7438 | 86 elems = [] |
87 for path in f[0]: | |
88 uri = '%s/diff/%s/%s' % (url, short(n), path) | |
89 elems.append(self.fileelem(path, url and uri, 'modify')) | |
90 for path in f[1]: | |
91 # TODO: copy/rename ? | |
92 uri = '%s/file/%s/%s' % (url, short(n), path) | |
93 elems.append(self.fileelem(path, url and uri, 'add')) | |
94 for path in f[2]: | |
95 elems.append(self.fileelem(path, '', 'remove')) | |
96 | |
97 return '\n'.join(elems) | |
98 | |
99 def sourceelem(self, project, module=None, branch=None): | |
100 msg = ['<source>', '<project>%s</project>' % saxutils.escape(project)] | |
101 if module: | |
102 msg.append('<module>%s</module>' % saxutils.escape(module)) | |
103 if branch: | |
104 msg.append('<branch>%s</branch>' % saxutils.escape(branch)) | |
105 msg.append('</source>') | |
106 | |
107 return '\n'.join(msg) | |
108 | |
109 def diffstat(self): | |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8541
diff
changeset
|
110 class patchbuf(object): |
7438 | 111 def __init__(self): |
112 self.lines = [] | |
113 # diffstat is stupid | |
114 self.name = 'cia' | |
115 def write(self, data): | |
116 self.lines.append(data) | |
117 def close(self): | |
118 pass | |
119 | |
120 n = self.ctx.node() | |
121 pbuf = patchbuf() | |
10611
e764f24a45ee
patch/diff: move patch.export() to cmdutil.export()
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10529
diff
changeset
|
122 cmdutil.export(self.cia.repo, [n], fp=pbuf) |
7438 | 123 return patch.diffstat(pbuf.lines) or '' |
124 | |
125 def logmsg(self): | |
126 diffstat = self.cia.diffstat and self.diffstat() or '' | |
127 self.cia.ui.pushbuffer() | |
128 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
|
129 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
|
130 url=self.url, diffstat=diffstat, |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
131 webroot=self.cia.root) |
7438 | 132 return self.cia.ui.popbuffer() |
133 | |
134 def xml(self): | |
135 n = short(self.ctx.node()) | |
136 src = self.sourceelem(self.cia.project, module=self.cia.module, | |
137 branch=self.ctx.branch()) | |
138 # unix timestamp | |
139 dt = self.ctx.date() | |
140 timestamp = dt[0] | |
141 | |
142 author = saxutils.escape(self.ctx.user()) | |
143 rev = '%d:%s' % (self.ctx.rev(), n) | |
144 log = saxutils.escape(self.logmsg()) | |
145 | |
14850
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
146 url = self.url |
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
147 if url and url[-1] == '/': |
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
148 url = url[:-1] |
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
149 url = url and '<url>%s/rev/%s</url>' % (saxutils.escape(url), n) or '' |
7438 | 150 |
151 msg = """ | |
152 <message> | |
153 <generator> | |
154 <name>Mercurial (hgcia)</name> | |
155 <version>%s</version> | |
156 <url>%s</url> | |
157 <user>%s</user> | |
158 </generator> | |
159 %s | |
160 <body> | |
161 <commit> | |
162 <author>%s</author> | |
163 <version>%s</version> | |
164 <log>%s</log> | |
165 %s | |
166 <files>%s</files> | |
167 </commit> | |
168 </body> | |
169 <timestamp>%d</timestamp> | |
170 </message> | |
171 """ % \ | |
172 (HGCIA_VERSION, saxutils.escape(HGCIA_URL), | |
173 saxutils.escape(self.cia.user), src, author, rev, log, url, | |
174 self.fileelems(), timestamp) | |
175 | |
176 return msg | |
177 | |
178 | |
179 class hgcia(object): | |
180 """ CIA notification class """ | |
181 | |
182 deftemplate = '{desc}' | |
183 dstemplate = '{desc}\n-- \n{diffstat}' | |
184 | |
185 def __init__(self, ui, repo): | |
186 self.ui = ui | |
187 self.repo = repo | |
188 | |
189 self.ciaurl = self.ui.config('cia', 'url', 'http://cia.vc') | |
190 self.user = self.ui.config('cia', 'user') | |
191 self.project = self.ui.config('cia', 'project') | |
192 self.module = self.ui.config('cia', 'module') | |
193 self.diffstat = self.ui.configbool('cia', 'diffstat') | |
194 self.emailfrom = self.ui.config('email', 'from') | |
195 self.dryrun = self.ui.configbool('cia', 'test') | |
196 self.url = self.ui.config('web', 'baseurl') | |
14850
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
197 # Default to -1 for backward compatibility |
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
198 self.stripcount = int(self.ui.config('cia', 'strip', -1)) |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
199 self.root = self.strip(self.repo.root) |
7438 | 200 |
201 style = self.ui.config('cia', 'style') | |
202 template = self.ui.config('cia', 'template') | |
203 if not template: | |
204 template = self.diffstat and self.dstemplate or self.deftemplate | |
205 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
|
206 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
|
207 style, False) |
7438 | 208 t.use_template(template) |
209 self.templater = t | |
210 | |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
211 def strip(self, path): |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
212 '''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
|
213 |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
214 path = util.pconvert(path) |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
215 count = self.stripcount |
14850
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
216 if count < 0: |
a95242af945c
hgcia: Set default value of strip to -1 (issue2891)
Cédric Krier <ced@b2ck.com>
parents:
14314
diff
changeset
|
217 return '' |
14314
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
218 while count > 0: |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
219 c = path.find('/') |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
220 if c == -1: |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
221 break |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
222 path = path[c + 1:] |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
223 count -= 1 |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
224 return path |
c322890b03e6
hgcia: Handle URL like in notify (issue2406)
Cédric Krier <ced@b2ck.com>
parents:
13878
diff
changeset
|
225 |
7438 | 226 def sendrpc(self, msg): |
227 srv = xmlrpclib.Server(self.ciaurl) | |
10529
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
228 res = srv.hub.deliver(msg) |
13551
bbfae32f178e
hgcia: accept "queued." xmlrpc return as success
Georg Brandl <georg@python.org>
parents:
11750
diff
changeset
|
229 if res is not True and res != 'queued.': |
10529
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
230 raise util.Abort(_('%s returned an error: %s') % |
076e8a8000a3
hgcia: report RPC errors
Brendan Cully <brendan@kublai.com>
parents:
10263
diff
changeset
|
231 (self.ciaurl, res)) |
7438 | 232 |
233 def sendemail(self, address, data): | |
234 p = email.Parser.Parser() | |
235 msg = p.parsestr(data) | |
236 msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2") | |
237 msg['To'] = address | |
238 msg['From'] = self.emailfrom | |
239 msg['Subject'] = 'DeliverXML' | |
240 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
|
241 msgtext = msg.as_string() |
7438 | 242 |
243 self.ui.status(_('hgcia: sending update to %s\n') % address) | |
244 mail.sendmail(self.ui, util.email(self.emailfrom), | |
245 [address], msgtext) | |
246 | |
247 | |
248 def hook(ui, repo, hooktype, node=None, url=None, **kwargs): | |
249 """ send CIA notification """ | |
250 def sendmsg(cia, ctx): | |
251 msg = ciamsg(cia, ctx).xml() | |
252 if cia.dryrun: | |
253 ui.write(msg) | |
254 elif cia.ciaurl.startswith('mailto:'): | |
255 if not cia.emailfrom: | |
256 raise util.Abort(_('email.from must be defined when ' | |
257 'sending by email')) | |
258 cia.sendemail(cia.ciaurl[7:], msg) | |
259 else: | |
260 cia.sendrpc(msg) | |
261 | |
262 n = bin(node) | |
263 cia = hgcia(ui, repo) | |
264 if not cia.user: | |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9260
diff
changeset
|
265 ui.debug('cia: no user specified') |
7438 | 266 return |
267 if not cia.project: | |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9260
diff
changeset
|
268 ui.debug('cia: no project specified') |
7438 | 269 return |
270 if hooktype == 'changegroup': | |
271 start = repo.changelog.rev(n) | |
272 end = len(repo.changelog) | |
273 for rev in xrange(start, end): | |
274 n = repo.changelog.node(rev) | |
275 ctx = repo.changectx(n) | |
276 sendmsg(cia, ctx) | |
277 else: | |
278 ctx = repo.changectx(n) | |
279 sendmsg(cia, ctx) |