##// END OF EJS Templates
color: use reST syntax for literal block
color: use reST syntax for literal block

File last commit:

r9200:6b4c527c default
r9206:c1a1b492 default
Show More
transplant.py
603 lines | 22.3 KiB | text/x-python | PythonLexer
Brendan Cully
Add transplant extension
r3714 # Patch transplanting extension for Mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2006, 2007 Brendan Cully <brendan@kublai.com>
Brendan Cully
Add transplant extension
r3714 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Brendan Cully
Add transplant extension
r3714
Dirkjan Ochtman
extensions: change descriptions for extensions providing a few commands
r8934 '''command to transplant changesets from another branch
Brendan Cully
Add transplant extension
r3714
This extension allows you to transplant patches from another branch.
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 Transplanted patches are recorded in .hg/transplant/transplants, as a map from
a changeset hash to its hash in the source repository.
Brendan Cully
Add transplant extension
r3714 '''
Dirkjan Ochtman
transplant: move docstrings before imports (see issue1466)
r7629 from mercurial.i18n import _
import os, tempfile
Matt Mackall
transplant: use match object rather than files for commit
r8703 from mercurial import bundlerepo, changegroup, cmdutil, hg, merge, match
Matt Mackall
errors: move revlog errors...
r7633 from mercurial import patch, revlog, util, error
Dirkjan Ochtman
transplant: move docstrings before imports (see issue1466)
r7629
Benoit Boissinot
use new style classes
r8778 class transplantentry(object):
Brendan Cully
Add transplant extension
r3714 def __init__(self, lnode, rnode):
self.lnode = lnode
self.rnode = rnode
Benoit Boissinot
use new style classes
r8778 class transplants(object):
Brendan Cully
Add transplant extension
r3714 def __init__(self, path=None, transplantfile=None, opener=None):
self.path = path
self.transplantfile = transplantfile
self.opener = opener
if not opener:
self.opener = util.opener(self.path)
self.transplants = []
self.dirty = False
self.read()
def read(self):
abspath = os.path.join(self.path, self.transplantfile)
if self.transplantfile and os.path.exists(abspath):
for line in self.opener(self.transplantfile).read().splitlines():
lnode, rnode = map(revlog.bin, line.split(':'))
self.transplants.append(transplantentry(lnode, rnode))
def write(self):
if self.dirty and self.transplantfile:
if not os.path.isdir(self.path):
os.mkdir(self.path)
fp = self.opener(self.transplantfile, 'w')
for c in self.transplants:
l, r = map(revlog.hex, (c.lnode, c.rnode))
fp.write(l + ':' + r + '\n')
fp.close()
self.dirty = False
def get(self, rnode):
return [t for t in self.transplants if t.rnode == rnode]
def set(self, lnode, rnode):
self.transplants.append(transplantentry(lnode, rnode))
self.dirty = True
def remove(self, transplant):
del self.transplants[self.transplants.index(transplant)]
self.dirty = True
Benoit Boissinot
use new style classes
r8778 class transplanter(object):
Brendan Cully
Add transplant extension
r3714 def __init__(self, ui, repo):
self.ui = ui
self.path = repo.join('transplant')
self.opener = util.opener(self.path)
Martin Geisler
transplant: wrapped long lines
r7744 self.transplants = transplants(self.path, 'transplants',
opener=self.opener)
Brendan Cully
Add transplant extension
r3714
def applied(self, repo, node, parent):
'''returns True if a node is already an ancestor of parent
or has already been transplanted'''
if hasnode(repo, node):
if node in repo.changelog.reachable(parent, stop=node):
return True
for t in self.transplants.get(node):
# it might have been stripped
if not hasnode(repo, t.lnode):
self.transplants.remove(t)
return False
if t.lnode in repo.changelog.reachable(parent, stop=t.lnode):
return True
return False
def apply(self, repo, source, revmap, merges, opts={}):
'''apply the revisions in revmap one by one in revision order'''
Matt Mackall
replace util.sort with sorted built-in...
r8209 revs = sorted(revmap)
Brendan Cully
Add transplant extension
r3714 p1, p2 = repo.dirstate.parents()
pulls = []
diffopts = patch.diffopts(self.ui, opts)
diffopts.git = True
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 lock = wlock = None
Brendan Cully
Add transplant extension
r3714 try:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 wlock = repo.wlock()
lock = repo.lock()
Brendan Cully
Add transplant extension
r3714 for rev in revs:
node = revmap[rev]
revstr = '%s:%s' % (rev, revlog.short(node))
if self.applied(repo, node, p1):
self.ui.warn(_('skipping already applied revision %s\n') %
revstr)
continue
parents = source.changelog.parents(node)
if not opts.get('filter'):
Martin Geisler
transplant: wrapped long lines
r7744 # If the changeset parent is the same as the
# wdir's parent, just pull it.
Brendan Cully
Add transplant extension
r3714 if parents[0] == p1:
pulls.append(node)
p1 = node
continue
if pulls:
if source != repo:
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 repo.pull(source, heads=pulls)
merge.update(repo, pulls[-1], False, False, None)
Brendan Cully
Add transplant extension
r3714 p1, p2 = repo.dirstate.parents()
pulls = []
domerge = False
if node in merges:
Martin Geisler
transplant: wrapped long lines
r7744 # pulling all the merge revs at once would mean we
# couldn't transplant after the latest even if
# transplants before them fail.
Brendan Cully
Add transplant extension
r3714 domerge = True
if not hasnode(repo, node):
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 repo.pull(source, heads=[node])
Brendan Cully
Add transplant extension
r3714
if parents[1] != revlog.nullid:
self.ui.note(_('skipping merge changeset %s:%s\n')
% (rev, revlog.short(node)))
patchfile = None
else:
fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-')
fp = os.fdopen(fd, 'w')
Dirkjan Ochtman
patch: turn patch.diff() into a generator...
r7308 gen = patch.diff(source, parents[0], node, opts=diffopts)
for chunk in gen:
fp.write(chunk)
Brendan Cully
Add transplant extension
r3714 fp.close()
del revmap[rev]
if patchfile or domerge:
try:
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 n = self.applyone(repo, node,
source.changelog.read(node),
Brendan Cully
Add transplant extension
r3714 patchfile, merge=domerge,
log=opts.get('log'),
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 filter=opts.get('filter'))
Brendan Cully
transplant: fix ignoring empty changesets (eg after filter)
r4251 if n and domerge:
Brendan Cully
Add transplant extension
r3714 self.ui.status(_('%s merged at %s\n') % (revstr,
revlog.short(n)))
Brendan Cully
transplant: fix ignoring empty changesets (eg after filter)
r4251 elif n:
Martin Geisler
transplant: wrapped long lines
r7744 self.ui.status(_('%s transplanted to %s\n')
% (revlog.short(node),
revlog.short(n)))
Brendan Cully
Add transplant extension
r3714 finally:
if patchfile:
os.unlink(patchfile)
if pulls:
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 repo.pull(source, heads=pulls)
merge.update(repo, pulls[-1], False, False, None)
Brendan Cully
Add transplant extension
r3714 finally:
self.saveseries(revmap, merges)
self.transplants.write()
Ronny Pfannschmidt
switch lock releasing in the extensions from gc to explicit
r8112 lock.release()
wlock.release()
Brendan Cully
Add transplant extension
r3714
def filter(self, filter, changelog, patchfile):
'''arbitrarily rewrite changeset before applying it'''
Martin Geisler
i18n: mark strings for translation in transplant extension
r6966 self.ui.status(_('filtering %s\n') % patchfile)
Brendan Cully
transplant: split filter args into changelog entry and patch
r3759 user, date, msg = (changelog[1], changelog[2], changelog[4])
fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-')
fp = os.fdopen(fd, 'w')
fp.write("# HG changeset patch\n")
fp.write("# User %s\n" % user)
fp.write("# Date %d %d\n" % date)
Brendan Cully
transplant: don't add extra newlines to changelog entry in filter
r3831 fp.write(changelog[4])
Brendan Cully
transplant: split filter args into changelog entry and patch
r3759 fp.close()
try:
util.system('%s %s %s' % (filter, util.shellquote(headerfile),
util.shellquote(patchfile)),
environ={'HGUSER': changelog[1]},
onerr=util.Abort, errprefix=_('filter failed'))
user, date, msg = self.parselog(file(headerfile))[1:4]
finally:
os.unlink(headerfile)
return (user, date, msg)
Brendan Cully
Add transplant extension
r3714
def applyone(self, repo, node, cl, patchfile, merge=False, log=False,
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 filter=None):
Brendan Cully
Add transplant extension
r3714 '''apply the patch in patchfile to the repository as a transplant'''
(manifest, user, (time, timezone), files, message) = cl[:5]
date = "%d %d" % (time, timezone)
extra = {'transplant_source': node}
if filter:
Brendan Cully
transplant: split filter args into changelog entry and patch
r3759 (user, date, message) = self.filter(filter, cl, patchfile)
Brendan Cully
Add transplant extension
r3714
if log:
Martin Geisler
do not translate commit messages...
r9183 # we don't translate messages inserted into commits
Brendan Cully
Add transplant extension
r3714 message += '\n(transplanted from %s)' % revlog.hex(node)
self.ui.status(_('applying %s\n') % revlog.short(node))
self.ui.note('%s %s\n%s\n' % (user, date, message))
if not patchfile and not merge:
raise util.Abort(_('can only omit patchfile if merging'))
if patchfile:
try:
files = {}
Brendan Cully
transplant: recover added/removed files after failed application
r3726 try:
Peter Arrenbrecht
cleanup: drop variables for unused return values...
r7874 patch.patch(patchfile, self.ui, cwd=repo.root,
Patrick Mezard
Make mq, record and transplant honor patch.eol
r8811 files=files, eolmode=None)
Brendan Cully
transplant: recover added/removed files after failed application
r3726 if not files:
Martin Geisler
transplant: wrapped long lines
r7744 self.ui.warn(_('%s: empty changeset')
% revlog.hex(node))
Brendan Cully
transplant: fix ignoring empty changesets (eg after filter)
r4251 return None
Brendan Cully
transplant: recover added/removed files after failed application
r3726 finally:
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 files = patch.updatedir(self.ui, repo, files)
Brendan Cully
Add transplant extension
r3714 except Exception, inst:
if filter:
os.unlink(patchfile)
Brendan Cully
transplant: clobber old series when transplant fails
r3757 seriespath = os.path.join(self.path, 'series')
if os.path.exists(seriespath):
os.unlink(seriespath)
Brendan Cully
Add transplant extension
r3714 p1 = repo.dirstate.parents()[0]
p2 = node
Brendan Cully
transplant: preserve filter changes in --continue log
r3725 self.log(user, date, message, p1, p2, merge=merge)
Brendan Cully
Add transplant extension
r3714 self.ui.write(str(inst) + '\n')
Martin Geisler
transplant: wrapped long lines
r7744 raise util.Abort(_('Fix up the merge and run '
'hg transplant --continue'))
Brendan Cully
Add transplant extension
r3714 else:
files = None
if merge:
p1, p2 = repo.dirstate.parents()
repo.dirstate.setparents(p1, node)
Matt Mackall
transplant: use match object rather than files for commit
r8703 m = match.always(repo.root, '')
else:
m = match.exact(repo.root, '', files)
Brendan Cully
Add transplant extension
r3714
Matt Mackall
commit: drop the now-unused files parameter
r8706 n = repo.commit(message, user, date, extra=extra, match=m)
Brendan Cully
Add transplant extension
r3714 if not merge:
self.transplants.set(n, node)
return n
def resume(self, repo, source, opts=None):
'''recover last transaction and apply remaining changesets'''
if os.path.exists(os.path.join(self.path, 'journal')):
n, node = self.recover(repo)
Brendan Cully
transplant: fix --continue; add --continue test
r3724 self.ui.status(_('%s transplanted as %s\n') % (revlog.short(node),
revlog.short(n)))
Brendan Cully
Add transplant extension
r3714 seriespath = os.path.join(self.path, 'series')
if not os.path.exists(seriespath):
Brendan Cully
transplant: log source node when recovering too.
r3758 self.transplants.write()
Brendan Cully
Add transplant extension
r3714 return
nodes, merges = self.readseries()
revmap = {}
for n in nodes:
revmap[source.changelog.rev(n)] = n
os.unlink(seriespath)
self.apply(repo, source, revmap, merges, opts)
def recover(self, repo):
'''commit working directory using journal metadata'''
node, user, date, message, parents = self.readlog()
merge = len(parents) == 2
if not user or not date or not message or not parents[0]:
raise util.Abort(_('transplant log file is corrupt'))
Brendan Cully
transplant: log source node when recovering too.
r3758 extra = {'transplant_source': node}
Brendan Cully
Add transplant extension
r3714 wlock = repo.wlock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
p1, p2 = repo.dirstate.parents()
if p1 != parents[0]:
raise util.Abort(
_('working dir not at transplant parent %s') %
revlog.hex(parents[0]))
if merge:
repo.dirstate.setparents(p1, parents[1])
Matt Mackall
commit: drop the now-unused files parameter
r8706 n = repo.commit(message, user, date, extra=extra)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if not n:
raise util.Abort(_('commit failed'))
if not merge:
self.transplants.set(n, node)
self.unlog()
Brendan Cully
Add transplant extension
r3714
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 return n, node
finally:
Ronny Pfannschmidt
switch lock releasing in the extensions from gc to explicit
r8112 wlock.release()
Brendan Cully
Add transplant extension
r3714
def readseries(self):
nodes = []
merges = []
cur = nodes
for line in self.opener('series').read().splitlines():
if line.startswith('# Merges'):
cur = merges
continue
cur.append(revlog.bin(line))
return (nodes, merges)
def saveseries(self, revmap, merges):
if not revmap:
return
if not os.path.isdir(self.path):
os.mkdir(self.path)
series = self.opener('series', 'w')
Matt Mackall
replace util.sort with sorted built-in...
r8209 for rev in sorted(revmap):
Brendan Cully
Add transplant extension
r3714 series.write(revlog.hex(revmap[rev]) + '\n')
if merges:
series.write('# Merges\n')
for m in merges:
series.write(revlog.hex(m) + '\n')
series.close()
Brendan Cully
transplant: split filter args into changelog entry and patch
r3759 def parselog(self, fp):
parents = []
message = []
node = revlog.nullid
inmsg = False
for line in fp.read().splitlines():
if inmsg:
message.append(line)
elif line.startswith('# User '):
user = line[7:]
elif line.startswith('# Date '):
date = line[7:]
elif line.startswith('# Node ID '):
node = revlog.bin(line[10:])
elif line.startswith('# Parent '):
parents.append(revlog.bin(line[9:]))
elif not line.startswith('#'):
inmsg = True
message.append(line)
return (node, user, date, '\n'.join(message), parents)
Thomas Arendsen Hein
Removed trailing whitespace and tabs from python files
r4516
Brendan Cully
transplant: preserve filter changes in --continue log
r3725 def log(self, user, date, message, p1, p2, merge=False):
Brendan Cully
Add transplant extension
r3714 '''journal changelog metadata for later recover'''
if not os.path.isdir(self.path):
os.mkdir(self.path)
fp = self.opener('journal', 'w')
Brendan Cully
transplant: preserve filter changes in --continue log
r3725 fp.write('# User %s\n' % user)
fp.write('# Date %s\n' % date)
Brendan Cully
Add transplant extension
r3714 fp.write('# Node ID %s\n' % revlog.hex(p2))
fp.write('# Parent ' + revlog.hex(p1) + '\n')
if merge:
fp.write('# Parent ' + revlog.hex(p2) + '\n')
Brendan Cully
transplant: preserve filter changes in --continue log
r3725 fp.write(message.rstrip() + '\n')
Brendan Cully
Add transplant extension
r3714 fp.close()
def readlog(self):
Brendan Cully
transplant: split filter args into changelog entry and patch
r3759 return self.parselog(self.opener('journal'))
Brendan Cully
Add transplant extension
r3714
def unlog(self):
'''remove changelog journal'''
absdst = os.path.join(self.path, 'journal')
if os.path.exists(absdst):
os.unlink(absdst)
def transplantfilter(self, repo, source, root):
def matchfn(node):
if self.applied(repo, node, root):
return False
if source.changelog.parents(node)[1] != revlog.nullid:
return False
extra = source.changelog.read(node)[5]
cnode = extra.get('transplant_source')
if cnode and self.applied(repo, cnode, root):
return False
return True
return matchfn
def hasnode(repo, node):
try:
return repo.changelog.rev(node) != None
Matt Mackall
errors: move revlog errors...
r7633 except error.RevlogError:
Brendan Cully
Add transplant extension
r3714 return False
def browserevs(ui, repo, nodes, opts):
'''interactively transplant changesets'''
def browsehelp(ui):
ui.write('y: transplant this changeset\n'
'n: skip this changeset\n'
'm: merge at this changeset\n'
'p: show patch\n'
'c: commit selected changesets\n'
'q: cancel transplant\n'
'?: show this help\n')
Brendan Cully
transplant: show_changeset moved to cmdutil
r3723 displayer = cmdutil.show_changeset(ui, repo, opts)
Brendan Cully
Add transplant extension
r3714 transplants = []
merges = []
for node in nodes:
Dirkjan Ochtman
cmdutil: use change contexts for cset-printer and cset-templater
r7369 displayer.show(repo[node])
Brendan Cully
Add transplant extension
r3714 action = None
while not action:
action = ui.prompt(_('apply changeset? [ynmpcq?]:'))
if action == '?':
browsehelp(ui)
action = None
elif action == 'p':
parent = repo.changelog.parents(node)[0]
Dirkjan Ochtman
patch: turn patch.diff() into a generator...
r7308 for chunk in patch.diff(repo, parent, node):
Martin Geisler
use ui instead of repo.ui when the former is in scope
r8615 ui.write(chunk)
Brendan Cully
Add transplant extension
r3714 action = None
elif action not in ('y', 'n', 'm', 'c', 'q'):
ui.write('no such option\n')
action = None
if action == 'y':
transplants.append(node)
elif action == 'm':
merges.append(node)
elif action == 'c':
break
elif action == 'q':
transplants = ()
merges = ()
break
return (transplants, merges)
def transplant(ui, repo, *revs, **opts):
'''transplant changesets from another branch
Selected changesets will be applied on top of the current working
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 directory with the log of the original changeset. If --log is specified,
Martin Geisler
transplant: better reST formatting
r9200 log messages will have a comment appended of the form::
Brendan Cully
Add transplant extension
r3714
Martin Geisler
transplant: better reST formatting
r9200 (transplanted from CHANGESETHASH)
Brendan Cully
Add transplant extension
r3714
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 You can rewrite the changelog message with the --filter option. Its
argument will be invoked with the current changelog message as $1 and the
patch as $2.
Brendan Cully
Add transplant extension
r3714
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 If --source/-s is specified, selects changesets from the named repository.
If --branch/-b is specified, selects changesets from the branch holding
the named revision, up to that revision. If --all/-a is specified, all
changesets on the branch will be transplanted, otherwise you will be
prompted to select the changesets you want.
Brendan Cully
Add transplant extension
r3714
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 hg transplant --branch REVISION --all will rebase the selected branch (up
to the named revision) onto your current working directory.
Brendan Cully
Add transplant extension
r3714
Martin Geisler
transplant: word-wrap help texts at 70 characters
r8000 You can optionally mark selected transplanted changesets as merge
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 changesets. You will not be prompted to transplant any ancestors of a
merged transplant, and you can merge descendants of them normally instead
of transplanting them.
Brendan Cully
Add transplant extension
r3714
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 If no merges or revisions are provided, hg transplant will start an
interactive changeset browser.
Brendan Cully
Add transplant extension
r3714
Martin Geisler
transplant: wrapped docstrings at 78 characters
r9076 If a changeset application fails, you can fix the merge by hand and then
resume where you left off by calling hg transplant --continue/-c.
Brendan Cully
Add transplant extension
r3714 '''
def getremotechanges(repo, url):
sourcerepo = ui.expandpath(url)
source = hg.repository(ui, sourcerepo)
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 common, incoming, rheads = repo.findcommonincoming(source, force=True)
Brendan Cully
Add transplant extension
r3714 if not incoming:
return (source, None, None)
bundle = None
if not source.local():
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 if source.capable('changegroupsubset'):
cg = source.changegroupsubset(incoming, rheads, 'incoming')
else:
cg = source.changegroup(incoming, 'incoming')
Brendan Cully
transplant: update to current writebundle API
r4049 bundle = changegroup.writebundle(cg, None, 'HG10UN')
Brendan Cully
Add transplant extension
r3714 source = bundlerepo.bundlerepository(ui, repo.root, bundle)
return (source, incoming, bundle)
def incwalk(repo, incoming, branches, match=util.always):
if not branches:
branches=None
for node in repo.changelog.nodesbetween(incoming, branches)[0]:
if match(node):
yield node
def transplantwalk(repo, root, branches, match=util.always):
if not branches:
branches = repo.heads()
ancestors = []
for branch in branches:
ancestors.append(repo.changelog.ancestor(root, branch))
for node in repo.changelog.nodesbetween(ancestors, branches)[0]:
if match(node):
yield node
def checkopts(opts, revs):
if opts.get('continue'):
if filter(lambda opt: opts.get(opt), ('branch', 'all', 'merge')):
Martin Geisler
transplant: wrapped long lines
r7744 raise util.Abort(_('--continue is incompatible with '
'branch, all or merge'))
Brendan Cully
Add transplant extension
r3714 return
if not (opts.get('source') or revs or
opts.get('merge') or opts.get('branch')):
Martin Geisler
transplant: wrapped long lines
r7744 raise util.Abort(_('no source URL, branch tag or revision '
'list provided'))
Brendan Cully
Add transplant extension
r3714 if opts.get('all'):
if not opts.get('branch'):
raise util.Abort(_('--all requires a branch revision'))
if revs:
Martin Geisler
transplant: wrapped long lines
r7744 raise util.Abort(_('--all is incompatible with a '
'revision list'))
Brendan Cully
Add transplant extension
r3714
checkopts(opts, revs)
if not opts.get('log'):
opts['log'] = ui.config('transplant', 'log')
if not opts.get('filter'):
opts['filter'] = ui.config('transplant', 'filter')
tp = transplanter(ui, repo)
p1, p2 = repo.dirstate.parents()
Brendan Cully
transplant: forbid transplant to nonempty repositories with no working directory....
r8176 if len(repo) > 0 and p1 == revlog.nullid:
raise util.Abort(_('no revision checked out'))
Brendan Cully
Add transplant extension
r3714 if not opts.get('continue'):
if p2 != revlog.nullid:
raise util.Abort(_('outstanding uncommitted merges'))
m, a, r, d = repo.status()[:4]
if m or a or r or d:
raise util.Abort(_('outstanding local changes'))
bundle = None
source = opts.get('source')
if source:
(source, incoming, bundle) = getremotechanges(repo, source)
else:
source = repo
try:
if opts.get('continue'):
Brendan Cully
transplant: fix --continue; add --continue test
r3724 tp.resume(repo, source, opts)
Brendan Cully
Add transplant extension
r3714 return
tf=tp.transplantfilter(repo, source, p1)
if opts.get('prune'):
prune = [source.lookup(r)
for r in cmdutil.revrange(source, opts.get('prune'))]
matchfn = lambda x: tf(x) and x not in prune
else:
matchfn = tf
branches = map(source.lookup, opts.get('branch', ()))
merges = map(source.lookup, opts.get('merge', ()))
revmap = {}
if revs:
for r in cmdutil.revrange(source, revs):
revmap[int(r)] = source.lookup(r)
elif opts.get('all') or not merges:
if source != repo:
Martin Geisler
transplant: wrapped long lines
r7744 alltransplants = incwalk(source, incoming, branches,
match=matchfn)
Brendan Cully
Add transplant extension
r3714 else:
Martin Geisler
transplant: wrapped long lines
r7744 alltransplants = transplantwalk(source, p1, branches,
match=matchfn)
Brendan Cully
Add transplant extension
r3714 if opts.get('all'):
revs = alltransplants
else:
revs, newmerges = browserevs(ui, source, alltransplants, opts)
merges.extend(newmerges)
for r in revs:
revmap[source.changelog.rev(r)] = r
for r in merges:
revmap[source.changelog.rev(r)] = r
tp.apply(repo, source, revmap, merges, opts)
finally:
if bundle:
Patrick Mezard
transplant: remote bundle source was not closed before deleting the fetched bundle....
r4072 source.close()
Brendan Cully
Add transplant extension
r3714 os.unlink(bundle)
cmdtable = {
"transplant":
(transplant,
[('s', 'source', '', _('pull patches from REPOSITORY')),
('b', 'branch', [], _('pull patches from branch BRANCH')),
('a', 'all', None, _('pull all changesets up to BRANCH')),
('p', 'prune', [], _('skip over REV')),
('m', 'merge', [], _('merge at REV')),
('', 'log', None, _('append transplant info to log message')),
Martin Geisler
transplant: wrapped long lines
r7744 ('c', 'continue', None, _('continue last transplant session '
'after repair')),
Brendan Cully
Add transplant extension
r3714 ('', 'filter', '', _('filter changesets through FILTER'))],
Martin Geisler
transplant: wrapped long lines
r7744 _('hg transplant [-s REPOSITORY] [-b BRANCH [-a]] [-p REV] '
'[-m REV] [REV]...'))
Brendan Cully
Add transplant extension
r3714 }