##// END OF EJS Templates
largefiles: update largefiles even if rebase is aborted by conflict...
largefiles: update largefiles even if rebase is aborted by conflict Before this patch, largefiles in the working directory aren't updated correctly, if rebase is aborted by conflict. This prevents users from viewing appropriate largefiles while resolving conflicts. While rebase, largefiles in the working directory are updated only at successful committing in the special code path of "lfilesrepo.commit()". To update largefiles even if rebase is aborted by conflict, this patch centralizes the logic of updating largefiles in the working directory into the "mergeupdate" wrapping "merge.update". This is a temporary way to fix with less changes. For fundamental resolution of this kind of problems in the future, largefiles in the working directory should be updated with other (normal) files simultaneously while "merge.update" execution: maybe by hooking "applyupdates". "Action list based updating" introduced by hooking "applyupdates" will also improve performance of updating, because it automatically decreases target files to be checked. Just after this patch, there are some improper things in "Case 0" code path of "lfilesrepo.commit()": - "updatelfiles" invocation is redundant for rebase - detailed comment doesn't meet to rebase behavior These will be resolved after the subsequent patch for transplant, because this code path is shared with transplant. Even though replacing "merge.update" in rebase extension by "hg.merge" can also avoid this problem, this patch chooses centralizing the logic into "mergeupdate", because: - "merge.update" invocation in rebase extension can't be directly replaced by "hg.merge", because: - rebase requires some extra arguments, which "hg.merge" doesn't take (e.g. "ancestor") - rebase doesn't require statistics information forcibly displayed in "hg.merge" - introducing "mergeupdate" can resolve also problem of some other code paths directly using "merge.update" largefiles in the working directory aren't updated regardless of the result of commands below, before this patch: - backout (for revisions other than the parent revision of the working directory without "--merge") - graft - histedit (for revisions other than the parent of the working directory When "partial" is specified, "merge.update" doesn't update dirstate entries for standins, even though standins themselves are updated. In this case, "normallookup" should be used to mark largefiles as "possibly dirty" forcibly, because applying "normal" on lfdirstate treats them as "clean" unexpectedly. This is reason why "normallookup=partial" is specified for "lfcommands.updatelfiles". This patch doesn't test "hg rebase --continue", because it doesn't work correctly if largefiles in the working directory are modified manually while resolving conflicts. This will be fixed in the next step of refactoring for largefiles. All changes of tests/*.t files other than test-largefiles-update.t in this patch come from invoking "updatelfiles" not after but before statistics output of "hg.update", "hg.clean" and "hg.merge".

File last commit:

r20667:e96e9f80 default
r22288:4e255984 default
Show More
hgcia.py
276 lines | 8.7 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 = []
for path in f[0]:
uri = '%s/diff/%s/%s' % (url, short(n), path)
elems.append(self.fileelem(path, url and uri, 'modify'))
for path in f[1]:
# TODO: copy/rename ?
uri = '%s/file/%s/%s' % (url, short(n), path)
elems.append(self.fileelem(path, url and uri, 'add'))
for path in f[2]:
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):
diffstat = self.cia.diffstat and self.diffstat() or ''
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:
template = self.diffstat and self.dstemplate or self.deftemplate
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)