##// END OF EJS Templates
jsonchangeset: set manifest node to "null" for workingctx...
jsonchangeset: set manifest node to "null" for workingctx Unlike changeset_printer, it does not hide the manifest field because JSON output will be parsed by machine where explicit "null" will be more useful than nothing.

File last commit:

r24306:6ddc86ee default
r24603:e74f819e default
Show More
hgcia.py
282 lines | 8.8 KiB | text/x-python | PythonLexer
Brendan Cully
Add hgcia to hgext
r7438 # Copyright (C) 2007-8 Brendan Cully <brendan@kublai.com>
Matt Mackall
Update license to GPLv2+
r10263 #
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Brendan Cully
Add hgcia to hgext
r7438
Dirkjan Ochtman
extensions: change descriptions for hook-providing extensions...
r8935 """hooks for integrating with the CIA.vc notification service
Brendan Cully
Add hgcia to hgext
r7438
Martin Geisler
hgcia: wrap docstrings at 70 characters
r9260 This is meant to be run as a changegroup or incoming hook. To
configure it, set the following options in your hgrc::
Brendan Cully
Add hgcia to hgext
r7438
Martin Geisler
hgcia: use reST syntax for literal block
r9208 [cia]
# your registered CIA user name
user = foo
# the name of the project in CIA
project = foo
# the module (subproject) (optional)
#module = foo
# Append a diffstat to the log message (optional)
#diffstat = False
# Template to use for log messages (optional)
CĆ©dric Krier
hgcia: Handle URL like in notify (issue2406)...
r14314 #template = {desc}\\n{baseurl}{webroot}/rev/{node}-- {diffstat}
Martin Geisler
hgcia: use reST syntax for literal block
r9208 # Style to use (optional)
#style = foo
# The URL of the CIA notification service (optional)
Mads Kiilerich
fix trivial spelling errors
r17424 # You can use mailto: URLs to send by email, e.g.
Martin Geisler
hgcia: use reST syntax for literal block
r9208 # mailto:cia@cia.vc
# Make sure to set email.from if you do this.
#url = http://cia.vc/
# print message instead of sending it (optional)
#test = False
CĆ©dric Krier
hgcia: Handle URL like in notify (issue2406)...
r14314 # number of slashes to strip for url paths
#strip = 0
Brendan Cully
Add hgcia to hgext
r7438
Martin Geisler
hgcia: use reST syntax for literal block
r9208 [hooks]
# one of these:
changegroup.cia = python:hgcia.hook
#incoming.cia = python:hgcia.hook
Brendan Cully
Add hgcia to hgext
r7438
Martin Geisler
hgcia: use reST syntax for literal block
r9208 [web]
# If you want hyperlinks (optional)
baseurl = http://server/path/to/repo
Brendan Cully
Add hgcia to hgext
r7438 """
from mercurial.i18n import _
Brodie Rao
hgcia/color: remove star imports...
r11750 from mercurial.node import bin, short
Brendan Cully
Add hgcia to hgext
r7438 from mercurial import cmdutil, patch, templater, util, mail
import email.Parser
Brodie Rao
cleanup: replace naked excepts with more specific ones
r16688 import socket, xmlrpclib
Brendan Cully
Add hgcia to hgext
r7438 from xml.sax import saxutils
Augie Fackler
hgext: mark all first-party extensions as such
r16743 testedwith = 'internal'
Brendan Cully
Add hgcia to hgext
r7438
socket_timeout = 30 # seconds
Brodie Rao
cleanup: replace naked excepts with more specific ones
r16688 if util.safehasattr(socket, 'setdefaulttimeout'):
Brendan Cully
Add hgcia to hgext
r7438 # set a timeout for the socket so you don't have to wait so looooong
# when cia.vc is having problems. requires python >= 2.3:
socket.setdefaulttimeout(socket_timeout)
HGCIA_VERSION = '0.1'
HGCIA_URL = 'http://hg.kublai.com/mercurial/hgcia'
class ciamsg(object):
""" A CIA message """
def __init__(self, cia, ctx):
self.cia = cia
self.ctx = ctx
self.url = self.cia.url
CĆ©dric Krier
hgcia: Handle URL like in notify (issue2406)...
r14314 if self.url:
self.url += self.cia.root
Brendan Cully
Add hgcia to hgext
r7438
def fileelem(self, path, uri, action):
if uri:
uri = ' uri=%s' % saxutils.quoteattr(uri)
return '<file%s action=%s>%s</file>' % (
uri, saxutils.quoteattr(action), saxutils.escape(path))
def fileelems(self):
n = self.ctx.node()
Matt Mackall
misc: replace .parents()[0] with p1()
r13878 f = self.cia.repo.status(self.ctx.p1().node(), n)
Brendan Cully
Add hgcia to hgext
r7438 url = self.url or ''
CĆ©dric Krier
hgcia: Set default value of strip to -1 (issue2891)...
r14850 if url and url[-1] == '/':
url = url[:-1]
Brendan Cully
Add hgcia to hgext
r7438 elems = []
Martin von Zweigbergk
hgcia: access status fields by name rather than index
r22917 for path in f.modified:
Brendan Cully
Add hgcia to hgext
r7438 uri = '%s/diff/%s/%s' % (url, short(n), path)
elems.append(self.fileelem(path, url and uri, 'modify'))
Martin von Zweigbergk
hgcia: access status fields by name rather than index
r22917 for path in f.added:
Brendan Cully
Add hgcia to hgext
r7438 # TODO: copy/rename ?
uri = '%s/file/%s/%s' % (url, short(n), path)
elems.append(self.fileelem(path, url and uri, 'add'))
Martin von Zweigbergk
hgcia: access status fields by name rather than index
r22917 for path in f.removed:
Brendan Cully
Add hgcia to hgext
r7438 elems.append(self.fileelem(path, '', 'remove'))
return '\n'.join(elems)
def sourceelem(self, project, module=None, branch=None):
msg = ['<source>', '<project>%s</project>' % saxutils.escape(project)]
if module:
msg.append('<module>%s</module>' % saxutils.escape(module))
if branch:
msg.append('<branch>%s</branch>' % saxutils.escape(branch))
msg.append('</source>')
return '\n'.join(msg)
def diffstat(self):
Benoit Boissinot
use new style classes
r8778 class patchbuf(object):
Brendan Cully
Add hgcia to hgext
r7438 def __init__(self):
self.lines = []
# diffstat is stupid
self.name = 'cia'
def write(self, data):
Matt Mackall
hgcia: fix diffstat support
r15776 self.lines += data.splitlines(True)
Brendan Cully
Add hgcia to hgext
r7438 def close(self):
pass
n = self.ctx.node()
pbuf = patchbuf()
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611 cmdutil.export(self.cia.repo, [n], fp=pbuf)
Brendan Cully
Add hgcia to hgext
r7438 return patch.diffstat(pbuf.lines) or ''
def logmsg(self):
Jordi GutiƩrrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if self.cia.diffstat:
diffstat = self.diffstat()
else:
diffstat = ''
Brendan Cully
Add hgcia to hgext
r7438 self.cia.ui.pushbuffer()
self.cia.templater.show(self.ctx, changes=self.ctx.changeset(),
CĆ©dric Krier
hgcia: Handle URL like in notify (issue2406)...
r14314 baseurl=self.cia.ui.config('web', 'baseurl'),
url=self.url, diffstat=diffstat,
webroot=self.cia.root)
Brendan Cully
Add hgcia to hgext
r7438 return self.cia.ui.popbuffer()
def xml(self):
n = short(self.ctx.node())
src = self.sourceelem(self.cia.project, module=self.cia.module,
branch=self.ctx.branch())
# unix timestamp
dt = self.ctx.date()
timestamp = dt[0]
author = saxutils.escape(self.ctx.user())
rev = '%d:%s' % (self.ctx.rev(), n)
log = saxutils.escape(self.logmsg())
CĆ©dric Krier
hgcia: Set default value of strip to -1 (issue2891)...
r14850 url = self.url
if url and url[-1] == '/':
url = url[:-1]
url = url and '<url>%s/rev/%s</url>' % (saxutils.escape(url), n) or ''
Brendan Cully
Add hgcia to hgext
r7438
msg = """
<message>
<generator>
<name>Mercurial (hgcia)</name>
<version>%s</version>
<url>%s</url>
<user>%s</user>
</generator>
%s
<body>
<commit>
<author>%s</author>
<version>%s</version>
<log>%s</log>
%s
<files>%s</files>
</commit>
</body>
<timestamp>%d</timestamp>
</message>
""" % \
(HGCIA_VERSION, saxutils.escape(HGCIA_URL),
saxutils.escape(self.cia.user), src, author, rev, log, url,
self.fileelems(), timestamp)
return msg
class hgcia(object):
""" CIA notification class """
deftemplate = '{desc}'
dstemplate = '{desc}\n-- \n{diffstat}'
def __init__(self, ui, repo):
self.ui = ui
self.repo = repo
self.ciaurl = self.ui.config('cia', 'url', 'http://cia.vc')
self.user = self.ui.config('cia', 'user')
self.project = self.ui.config('cia', 'project')
self.module = self.ui.config('cia', 'module')
self.diffstat = self.ui.configbool('cia', 'diffstat')
self.emailfrom = self.ui.config('email', 'from')
self.dryrun = self.ui.configbool('cia', 'test')
self.url = self.ui.config('web', 'baseurl')
CĆ©dric Krier
hgcia: Set default value of strip to -1 (issue2891)...
r14850 # Default to -1 for backward compatibility
self.stripcount = int(self.ui.config('cia', 'strip', -1))
CĆ©dric Krier
hgcia: Handle URL like in notify (issue2406)...
r14314 self.root = self.strip(self.repo.root)
Brendan Cully
Add hgcia to hgext
r7438
style = self.ui.config('cia', 'style')
template = self.ui.config('cia', 'template')
if not template:
Jordi GutiƩrrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if self.diffstat:
template = self.dstemplate
else:
template = self.deftemplate
Brendan Cully
Add hgcia to hgext
r7438 template = templater.parsestring(template, quoted=False)
Jim Correia
add --git option to commands supporting --patch (log, incoming, history, tip)...
r7762 t = cmdutil.changeset_templater(self.ui, self.repo, False, None,
Matt Mackall
changeset_templater: remove use_template method
r20667 template, style, False)
Brendan Cully
Add hgcia to hgext
r7438 self.templater = t
CĆ©dric Krier
hgcia: Handle URL like in notify (issue2406)...
r14314 def strip(self, path):
'''strip leading slashes from local path, turn into web-safe path.'''
path = util.pconvert(path)
count = self.stripcount
CĆ©dric Krier
hgcia: Set default value of strip to -1 (issue2891)...
r14850 if count < 0:
return ''
CĆ©dric Krier
hgcia: Handle URL like in notify (issue2406)...
r14314 while count > 0:
c = path.find('/')
if c == -1:
break
path = path[c + 1:]
count -= 1
return path
Brendan Cully
Add hgcia to hgext
r7438 def sendrpc(self, msg):
srv = xmlrpclib.Server(self.ciaurl)
Brendan Cully
hgcia: report RPC errors
r10529 res = srv.hub.deliver(msg)
Georg Brandl
hgcia: accept "queued." xmlrpc return as success
r13551 if res is not True and res != 'queued.':
Brendan Cully
hgcia: report RPC errors
r10529 raise util.Abort(_('%s returned an error: %s') %
(self.ciaurl, res))
Brendan Cully
Add hgcia to hgext
r7438
def sendemail(self, address, data):
p = email.Parser.Parser()
msg = p.parsestr(data)
msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2")
msg['To'] = address
msg['From'] = self.emailfrom
msg['Subject'] = 'DeliverXML'
msg['Content-type'] = 'text/xml'
Nicolas Dumazet
for calls expecting bool args, pass bool instead of int...
r9136 msgtext = msg.as_string()
Brendan Cully
Add hgcia to hgext
r7438
self.ui.status(_('hgcia: sending update to %s\n') % address)
mail.sendmail(self.ui, util.email(self.emailfrom),
[address], msgtext)
def hook(ui, repo, hooktype, node=None, url=None, **kwargs):
""" send CIA notification """
def sendmsg(cia, ctx):
msg = ciamsg(cia, ctx).xml()
if cia.dryrun:
ui.write(msg)
elif cia.ciaurl.startswith('mailto:'):
if not cia.emailfrom:
raise util.Abort(_('email.from must be defined when '
'sending by email'))
cia.sendemail(cia.ciaurl[7:], msg)
else:
cia.sendrpc(msg)
n = bin(node)
cia = hgcia(ui, repo)
if not cia.user:
Martin Geisler
do not attempt to translate ui.debug output
r9467 ui.debug('cia: no user specified')
Brendan Cully
Add hgcia to hgext
r7438 return
if not cia.project:
Martin Geisler
do not attempt to translate ui.debug output
r9467 ui.debug('cia: no project specified')
Brendan Cully
Add hgcia to hgext
r7438 return
if hooktype == 'changegroup':
start = repo.changelog.rev(n)
end = len(repo.changelog)
for rev in xrange(start, end):
n = repo.changelog.node(rev)
ctx = repo.changectx(n)
sendmsg(cia, ctx)
else:
ctx = repo.changectx(n)
sendmsg(cia, ctx)