##// END OF EJS Templates
Add hgcia to hgext
Brendan Cully -
r7438:b80b9448 default
parent child Browse files
Show More
@@ -0,0 +1,245 b''
1 # Copyright (C) 2007-8 Brendan Cully <brendan@kublai.com>
2 # Published under the GNU GPL
3
4 """CIA notification
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)
19 #template = {desc}\n{baseurl}/rev/{node}-- {diffstat}
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):
102 class patchbuf:
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)
191 t = cmdutil.changeset_templater(self.ui, self.repo, False, style, False)
192 t.use_template(template)
193 self.templater = t
194
195 def sendrpc(self, msg):
196 srv = xmlrpclib.Server(self.ciaurl)
197 srv.hub.deliver(msg)
198
199 def sendemail(self, address, data):
200 p = email.Parser.Parser()
201 msg = p.parsestr(data)
202 msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2")
203 msg['To'] = address
204 msg['From'] = self.emailfrom
205 msg['Subject'] = 'DeliverXML'
206 msg['Content-type'] = 'text/xml'
207 msgtext = msg.as_string(0)
208
209 self.ui.status(_('hgcia: sending update to %s\n') % address)
210 mail.sendmail(self.ui, util.email(self.emailfrom),
211 [address], msgtext)
212
213
214 def hook(ui, repo, hooktype, node=None, url=None, **kwargs):
215 """ send CIA notification """
216 def sendmsg(cia, ctx):
217 msg = ciamsg(cia, ctx).xml()
218 if cia.dryrun:
219 ui.write(msg)
220 elif cia.ciaurl.startswith('mailto:'):
221 if not cia.emailfrom:
222 raise util.Abort(_('email.from must be defined when '
223 'sending by email'))
224 cia.sendemail(cia.ciaurl[7:], msg)
225 else:
226 cia.sendrpc(msg)
227
228 n = bin(node)
229 cia = hgcia(ui, repo)
230 if not cia.user:
231 ui.debug(_('cia: no user specified'))
232 return
233 if not cia.project:
234 ui.debug(_('cia: no project specified'))
235 return
236 if hooktype == 'changegroup':
237 start = repo.changelog.rev(n)
238 end = len(repo.changelog)
239 for rev in xrange(start, end):
240 n = repo.changelog.node(rev)
241 ctx = repo.changectx(n)
242 sendmsg(cia, ctx)
243 else:
244 ctx = repo.changectx(n)
245 sendmsg(cia, ctx)
@@ -0,0 +1,23 b''
1 #!/bin/sh
2
3 cat >> $HGRCPATH <<EOF
4 [extensions]
5 hgcia=
6
7 [hooks]
8 changegroup.cia = python:hgext.hgcia.hook
9
10 [cia]
11 user = testuser
12 project = testproject
13 test = True
14 EOF
15
16 hg init src
17 hg init cia
18
19 cd src
20 echo foo > foo
21 hg ci -Amfoo
22
23 hg push ../cia
@@ -0,0 +1,30 b''
1 adding foo
2 pushing to ../cia
3 searching for changes
4 adding changesets
5 adding manifests
6 adding file changes
7 added 1 changesets with 1 changes to 1 files
8
9 <message>
10 <generator>
11 <name>Mercurial (hgcia)</name>
12 <version>0.1</version>
13 <url>http://hg.kublai.com/mercurial/hgcia</url>
14 <user>testuser</user>
15 </generator>
16 <source>
17 <project>testproject</project>
18 <branch>default</branch>
19 </source>
20 <body>
21 <commit>
22 <author>test</author>
23 <version>0:e63c23eaa88a</version>
24 <log>foo</log>
25
26 <files><file action="add">foo</file></files>
27 </commit>
28 </body>
29 <timestamp>0</timestamp>
30 </message>
General Comments 0
You need to be logged in to leave comments. Login now