Mercurial > hg
annotate hgext/transplant.py @ 16365:5d61e007d957
mq: use exact matching in the second dirstate walking for efficiency of 'qnew'
'hg qnew' with pattern/-I/-X creates matching object with them, and
uses it twice for 'dirstate.walk()': via 'repo.status()' and
'repo.commit()'.
this may cause full manifest scan in the second 'dirstate.walk()',
even though mq already knows complete target filenames at the first
'dirstate.walk()'.
this patch creates exact matching object also in this case, and use it
at 'repo.commit()' invocation to avoid full manifest scan in the
second 'dirstate.walk()'.
even though 'inclsubs' is added to 'pats' for original matching
object, it is also passed to exact matching object, because
subrepositories are deleted from result of 'dirstate.walk()' at the
end of it.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Thu, 05 Apr 2012 23:52:06 +0900 |
parents | f7db54b832af |
children | f2ba409dbb0f |
rev | line source |
---|---|
3714 | 1 # Patch transplanting extension for Mercurial |
2 # | |
4635
63b9d2deed48
Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4516
diff
changeset
|
3 # Copyright 2006, 2007 Brendan Cully <brendan@kublai.com> |
3714 | 4 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8209
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
3714 | 7 |
8934
9dda4c73fc3b
extensions: change descriptions for extensions providing a few commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
8894
diff
changeset
|
8 '''command to transplant changesets from another branch |
3714 | 9 |
10 This extension allows you to transplant patches from another branch. | |
11 | |
8000
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
12 Transplanted patches are recorded in .hg/transplant/transplants, as a |
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
13 map from a changeset hash to its hash in the source repository. |
3714 | 14 ''' |
15 | |
7629
97253bcb44a8
transplant: move docstrings before imports (see issue1466)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7415
diff
changeset
|
16 from mercurial.i18n import _ |
97253bcb44a8
transplant: move docstrings before imports (see issue1466)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7415
diff
changeset
|
17 import os, tempfile |
14393
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
18 from mercurial.node import short |
14319
b33f3e35efb0
scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents:
14308
diff
changeset
|
19 from mercurial import bundlerepo, hg, merge, match |
b33f3e35efb0
scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents:
14308
diff
changeset
|
20 from mercurial import patch, revlog, scmutil, util, error, cmdutil |
13689
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
21 from mercurial import revset, templatekw |
7629
97253bcb44a8
transplant: move docstrings before imports (see issue1466)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7415
diff
changeset
|
22 |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
23 cmdtable = {} |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
24 command = cmdutil.command(cmdtable) |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
25 |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8706
diff
changeset
|
26 class transplantentry(object): |
3714 | 27 def __init__(self, lnode, rnode): |
28 self.lnode = lnode | |
29 self.rnode = rnode | |
30 | |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8706
diff
changeset
|
31 class transplants(object): |
3714 | 32 def __init__(self, path=None, transplantfile=None, opener=None): |
33 self.path = path | |
34 self.transplantfile = transplantfile | |
35 self.opener = opener | |
36 | |
37 if not opener: | |
13970
d13913355390
move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents:
13878
diff
changeset
|
38 self.opener = scmutil.opener(self.path) |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
39 self.transplants = {} |
3714 | 40 self.dirty = False |
41 self.read() | |
42 | |
43 def read(self): | |
44 abspath = os.path.join(self.path, self.transplantfile) | |
45 if self.transplantfile and os.path.exists(abspath): | |
14168
135e244776f0
prevent transient leaks of file handle by using new helper functions
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14161
diff
changeset
|
46 for line in self.opener.read(self.transplantfile).splitlines(): |
3714 | 47 lnode, rnode = map(revlog.bin, line.split(':')) |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
48 list = self.transplants.setdefault(rnode, []) |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
49 list.append(transplantentry(lnode, rnode)) |
3714 | 50 |
51 def write(self): | |
52 if self.dirty and self.transplantfile: | |
53 if not os.path.isdir(self.path): | |
54 os.mkdir(self.path) | |
55 fp = self.opener(self.transplantfile, 'w') | |
12349
7340b0fa049a
transplant: fix var name conflict introduced by 2912881c2a98
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12347
diff
changeset
|
56 for list in self.transplants.itervalues(): |
7340b0fa049a
transplant: fix var name conflict introduced by 2912881c2a98
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12347
diff
changeset
|
57 for t in list: |
7340b0fa049a
transplant: fix var name conflict introduced by 2912881c2a98
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12347
diff
changeset
|
58 l, r = map(revlog.hex, (t.lnode, t.rnode)) |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
59 fp.write(l + ':' + r + '\n') |
3714 | 60 fp.close() |
61 self.dirty = False | |
62 | |
63 def get(self, rnode): | |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
64 return self.transplants.get(rnode) or [] |
3714 | 65 |
66 def set(self, lnode, rnode): | |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
67 list = self.transplants.setdefault(rnode, []) |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
68 list.append(transplantentry(lnode, rnode)) |
3714 | 69 self.dirty = True |
70 | |
71 def remove(self, transplant): | |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
72 list = self.transplants.get(transplant.rnode) |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
73 if list: |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
74 del list[list.index(transplant)] |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
75 self.dirty = True |
3714 | 76 |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8706
diff
changeset
|
77 class transplanter(object): |
3714 | 78 def __init__(self, ui, repo): |
79 self.ui = ui | |
80 self.path = repo.join('transplant') | |
13970
d13913355390
move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents:
13878
diff
changeset
|
81 self.opener = scmutil.opener(self.path) |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
82 self.transplants = transplants(self.path, 'transplants', |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
83 opener=self.opener) |
15220
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
84 self.editor = None |
3714 | 85 |
86 def applied(self, repo, node, parent): | |
87 '''returns True if a node is already an ancestor of parent | |
88 or has already been transplanted''' | |
89 if hasnode(repo, node): | |
90 if node in repo.changelog.reachable(parent, stop=node): | |
91 return True | |
92 for t in self.transplants.get(node): | |
93 # it might have been stripped | |
94 if not hasnode(repo, t.lnode): | |
95 self.transplants.remove(t) | |
96 return False | |
97 if t.lnode in repo.changelog.reachable(parent, stop=t.lnode): | |
98 return True | |
99 return False | |
100 | |
101 def apply(self, repo, source, revmap, merges, opts={}): | |
102 '''apply the revisions in revmap one by one in revision order''' | |
8209
a1a5a57efe90
replace util.sort with sorted built-in
Matt Mackall <mpm@selenic.com>
parents:
8176
diff
changeset
|
103 revs = sorted(revmap) |
3714 | 104 p1, p2 = repo.dirstate.parents() |
105 pulls = [] | |
106 diffopts = patch.diffopts(self.ui, opts) | |
107 diffopts.git = True | |
108 | |
15204
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
109 lock = wlock = tr = None |
3714 | 110 try: |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
111 wlock = repo.wlock() |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
112 lock = repo.lock() |
15204
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
113 tr = repo.transaction('transplant') |
3714 | 114 for rev in revs: |
115 node = revmap[rev] | |
14393
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
116 revstr = '%s:%s' % (rev, short(node)) |
3714 | 117 |
118 if self.applied(repo, node, p1): | |
119 self.ui.warn(_('skipping already applied revision %s\n') % | |
120 revstr) | |
121 continue | |
122 | |
123 parents = source.changelog.parents(node) | |
124 if not opts.get('filter'): | |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
125 # If the changeset parent is the same as the |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
126 # wdir's parent, just pull it. |
3714 | 127 if parents[0] == p1: |
128 pulls.append(node) | |
129 p1 = node | |
130 continue | |
131 if pulls: | |
132 if source != repo: | |
4917
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
133 repo.pull(source, heads=pulls) |
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
134 merge.update(repo, pulls[-1], False, False, None) |
3714 | 135 p1, p2 = repo.dirstate.parents() |
136 pulls = [] | |
137 | |
138 domerge = False | |
139 if node in merges: | |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
140 # pulling all the merge revs at once would mean we |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
141 # couldn't transplant after the latest even if |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
142 # transplants before them fail. |
3714 | 143 domerge = True |
144 if not hasnode(repo, node): | |
4917
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
145 repo.pull(source, heads=[node]) |
3714 | 146 |
147 if parents[1] != revlog.nullid: | |
148 self.ui.note(_('skipping merge changeset %s:%s\n') | |
14393
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
149 % (rev, short(node))) |
3714 | 150 patchfile = None |
151 else: | |
152 fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-') | |
153 fp = os.fdopen(fd, 'w') | |
7308
b6f5490effbf
patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
154 gen = patch.diff(source, parents[0], node, opts=diffopts) |
b6f5490effbf
patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
155 for chunk in gen: |
b6f5490effbf
patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
156 fp.write(chunk) |
3714 | 157 fp.close() |
158 | |
159 del revmap[rev] | |
160 if patchfile or domerge: | |
161 try: | |
4917
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
162 n = self.applyone(repo, node, |
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
163 source.changelog.read(node), |
3714 | 164 patchfile, merge=domerge, |
165 log=opts.get('log'), | |
4917
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
166 filter=opts.get('filter')) |
4251
e76e52145c3d
transplant: fix ignoring empty changesets (eg after filter)
Brendan Cully <brendan@kublai.com>
parents:
4072
diff
changeset
|
167 if n and domerge: |
3714 | 168 self.ui.status(_('%s merged at %s\n') % (revstr, |
14393
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
169 short(n))) |
4251
e76e52145c3d
transplant: fix ignoring empty changesets (eg after filter)
Brendan Cully <brendan@kublai.com>
parents:
4072
diff
changeset
|
170 elif n: |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
171 self.ui.status(_('%s transplanted to %s\n') |
14393
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
172 % (short(node), |
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
173 short(n))) |
3714 | 174 finally: |
175 if patchfile: | |
176 os.unlink(patchfile) | |
15204
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
177 tr.close() |
3714 | 178 if pulls: |
4917
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
179 repo.pull(source, heads=pulls) |
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
180 merge.update(repo, pulls[-1], False, False, None) |
3714 | 181 finally: |
182 self.saveseries(revmap, merges) | |
183 self.transplants.write() | |
15204
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
184 if tr: |
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
185 tr.release() |
8112
6ee71f78497c
switch lock releasing in the extensions from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8076
diff
changeset
|
186 lock.release() |
6ee71f78497c
switch lock releasing in the extensions from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8076
diff
changeset
|
187 wlock.release() |
3714 | 188 |
13579
3cbb3c57a50e
transplant: added 'HGREVISION' variable to the environment passed to the 'filter' command
Luke Plant <L.Plant.98@cantab.net>
parents:
13031
diff
changeset
|
189 def filter(self, filter, node, changelog, patchfile): |
3714 | 190 '''arbitrarily rewrite changeset before applying it''' |
191 | |
6966
057ced2b8543
i18n: mark strings for translation in transplant extension
Martin Geisler <mg@daimi.au.dk>
parents:
6762
diff
changeset
|
192 self.ui.status(_('filtering %s\n') % patchfile) |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
193 user, date, msg = (changelog[1], changelog[2], changelog[4]) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
194 fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-') |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
195 fp = os.fdopen(fd, 'w') |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
196 fp.write("# HG changeset patch\n") |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
197 fp.write("# User %s\n" % user) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
198 fp.write("# Date %d %d\n" % date) |
9433
f01a22096f1f
transplant: Add trailing LF in tmp file for filtering
Mads Kiilerich <mads@kiilerich.com>
parents:
9183
diff
changeset
|
199 fp.write(msg + '\n') |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
200 fp.close() |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
201 |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
202 try: |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
203 util.system('%s %s %s' % (filter, util.shellquote(headerfile), |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
204 util.shellquote(patchfile)), |
13579
3cbb3c57a50e
transplant: added 'HGREVISION' variable to the environment passed to the 'filter' command
Luke Plant <L.Plant.98@cantab.net>
parents:
13031
diff
changeset
|
205 environ={'HGUSER': changelog[1], |
3cbb3c57a50e
transplant: added 'HGREVISION' variable to the environment passed to the 'filter' command
Luke Plant <L.Plant.98@cantab.net>
parents:
13031
diff
changeset
|
206 'HGREVISION': revlog.hex(node), |
3cbb3c57a50e
transplant: added 'HGREVISION' variable to the environment passed to the 'filter' command
Luke Plant <L.Plant.98@cantab.net>
parents:
13031
diff
changeset
|
207 }, |
14741
39235b398248
transplant: use ui out descriptor when calling util.system
Idan Kamara <idankk86@gmail.com>
parents:
14564
diff
changeset
|
208 onerr=util.Abort, errprefix=_('filter failed'), |
39235b398248
transplant: use ui out descriptor when calling util.system
Idan Kamara <idankk86@gmail.com>
parents:
14564
diff
changeset
|
209 out=self.ui.fout) |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
210 user, date, msg = self.parselog(file(headerfile))[1:4] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
211 finally: |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
212 os.unlink(headerfile) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
213 |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
214 return (user, date, msg) |
3714 | 215 |
216 def applyone(self, repo, node, cl, patchfile, merge=False, log=False, | |
4917
126f527b3ba3
Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents:
4915
diff
changeset
|
217 filter=None): |
3714 | 218 '''apply the patch in patchfile to the repository as a transplant''' |
219 (manifest, user, (time, timezone), files, message) = cl[:5] | |
220 date = "%d %d" % (time, timezone) | |
221 extra = {'transplant_source': node} | |
222 if filter: | |
13579
3cbb3c57a50e
transplant: added 'HGREVISION' variable to the environment passed to the 'filter' command
Luke Plant <L.Plant.98@cantab.net>
parents:
13031
diff
changeset
|
223 (user, date, message) = self.filter(filter, node, cl, patchfile) |
3714 | 224 |
225 if log: | |
9183
d0225fa2f6c4
do not translate commit messages
Martin Geisler <mg@lazybytes.net>
parents:
8934
diff
changeset
|
226 # we don't translate messages inserted into commits |
3714 | 227 message += '\n(transplanted from %s)' % revlog.hex(node) |
228 | |
14393
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
229 self.ui.status(_('applying %s\n') % short(node)) |
3714 | 230 self.ui.note('%s %s\n%s\n' % (user, date, message)) |
231 | |
232 if not patchfile and not merge: | |
233 raise util.Abort(_('can only omit patchfile if merging')) | |
234 if patchfile: | |
235 try: | |
14564
65f4512e40e4
patch: turn patch() touched files dict into a set
Patrick Mezard <pmezard@gmail.com>
parents:
14556
diff
changeset
|
236 files = set() |
14382
2d16f15da7bd
patch: remove patch.patch() cwd argument
Patrick Mezard <pmezard@gmail.com>
parents:
14319
diff
changeset
|
237 patch.patch(self.ui, repo, patchfile, files=files, eolmode=None) |
14260
00a881581400
patch: make patch()/internalpatch() always update the dirstate
Patrick Mezard <pmezard@gmail.com>
parents:
14259
diff
changeset
|
238 files = list(files) |
00a881581400
patch: make patch()/internalpatch() always update the dirstate
Patrick Mezard <pmezard@gmail.com>
parents:
14259
diff
changeset
|
239 if not files: |
00a881581400
patch: make patch()/internalpatch() always update the dirstate
Patrick Mezard <pmezard@gmail.com>
parents:
14259
diff
changeset
|
240 self.ui.warn(_('%s: empty changeset') % revlog.hex(node)) |
00a881581400
patch: make patch()/internalpatch() always update the dirstate
Patrick Mezard <pmezard@gmail.com>
parents:
14259
diff
changeset
|
241 return None |
3714 | 242 except Exception, inst: |
3757
faed44bab17b
transplant: clobber old series when transplant fails
Brendan Cully <brendan@kublai.com>
parents:
3752
diff
changeset
|
243 seriespath = os.path.join(self.path, 'series') |
faed44bab17b
transplant: clobber old series when transplant fails
Brendan Cully <brendan@kublai.com>
parents:
3752
diff
changeset
|
244 if os.path.exists(seriespath): |
faed44bab17b
transplant: clobber old series when transplant fails
Brendan Cully <brendan@kublai.com>
parents:
3752
diff
changeset
|
245 os.unlink(seriespath) |
13878
a8d13ee0ce68
misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents:
13790
diff
changeset
|
246 p1 = repo.dirstate.p1() |
3714 | 247 p2 = node |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
248 self.log(user, date, message, p1, p2, merge=merge) |
3714 | 249 self.ui.write(str(inst) + '\n') |
12067
a4fbbe0fbc38
Lowercase error messages
Martin Geisler <mg@lazybytes.net>
parents:
11638
diff
changeset
|
250 raise util.Abort(_('fix up the merge and run ' |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
251 'hg transplant --continue')) |
3714 | 252 else: |
253 files = None | |
254 if merge: | |
255 p1, p2 = repo.dirstate.parents() | |
256 repo.dirstate.setparents(p1, node) | |
8703
8676dd819444
transplant: use match object rather than files for commit
Matt Mackall <mpm@selenic.com>
parents:
8615
diff
changeset
|
257 m = match.always(repo.root, '') |
8676dd819444
transplant: use match object rather than files for commit
Matt Mackall <mpm@selenic.com>
parents:
8615
diff
changeset
|
258 else: |
8676dd819444
transplant: use match object rather than files for commit
Matt Mackall <mpm@selenic.com>
parents:
8615
diff
changeset
|
259 m = match.exact(repo.root, '', files) |
3714 | 260 |
15220
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
261 n = repo.commit(message, user, date, extra=extra, match=m, |
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
262 editor=self.editor) |
11638
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
263 if not n: |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
264 # Crash here to prevent an unclear crash later, in |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
265 # transplants.write(). This can happen if patch.patch() |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
266 # does nothing but claims success or if repo.status() fails |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
267 # to report changes done by patch.patch(). These both |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
268 # appear to be bugs in other parts of Mercurial, but dying |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
269 # here, as soon as we can detect the problem, is preferable |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
270 # to silently dropping changesets on the floor. |
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
271 raise RuntimeError('nothing committed after transplant') |
3714 | 272 if not merge: |
273 self.transplants.set(n, node) | |
274 | |
275 return n | |
276 | |
277 def resume(self, repo, source, opts=None): | |
278 '''recover last transaction and apply remaining changesets''' | |
279 if os.path.exists(os.path.join(self.path, 'journal')): | |
280 n, node = self.recover(repo) | |
14393
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
281 self.ui.status(_('%s transplanted as %s\n') % (short(node), |
bdf44e63a94c
revlog: stop exporting node.short
Matt Mackall <mpm@selenic.com>
parents:
14382
diff
changeset
|
282 short(n))) |
3714 | 283 seriespath = os.path.join(self.path, 'series') |
284 if not os.path.exists(seriespath): | |
3758
889f7e74a0d9
transplant: log source node when recovering too.
Brendan Cully <brendan@kublai.com>
parents:
3757
diff
changeset
|
285 self.transplants.write() |
3714 | 286 return |
287 nodes, merges = self.readseries() | |
288 revmap = {} | |
289 for n in nodes: | |
290 revmap[source.changelog.rev(n)] = n | |
291 os.unlink(seriespath) | |
292 | |
293 self.apply(repo, source, revmap, merges, opts) | |
294 | |
295 def recover(self, repo): | |
296 '''commit working directory using journal metadata''' | |
297 node, user, date, message, parents = self.readlog() | |
298 merge = len(parents) == 2 | |
299 | |
300 if not user or not date or not message or not parents[0]: | |
301 raise util.Abort(_('transplant log file is corrupt')) | |
302 | |
3758
889f7e74a0d9
transplant: log source node when recovering too.
Brendan Cully <brendan@kublai.com>
parents:
3757
diff
changeset
|
303 extra = {'transplant_source': node} |
3714 | 304 wlock = repo.wlock() |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
305 try: |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
306 p1, p2 = repo.dirstate.parents() |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
307 if p1 != parents[0]: |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
308 raise util.Abort( |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
309 _('working dir not at transplant parent %s') % |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
310 revlog.hex(parents[0])) |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
311 if merge: |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
312 repo.dirstate.setparents(p1, parents[1]) |
15220
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
313 n = repo.commit(message, user, date, extra=extra, |
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
314 editor=self.editor) |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
315 if not n: |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
316 raise util.Abort(_('commit failed')) |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
317 if not merge: |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
318 self.transplants.set(n, node) |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
319 self.unlog() |
3714 | 320 |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
321 return n, node |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
322 finally: |
8112
6ee71f78497c
switch lock releasing in the extensions from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8076
diff
changeset
|
323 wlock.release() |
3714 | 324 |
325 def readseries(self): | |
326 nodes = [] | |
327 merges = [] | |
328 cur = nodes | |
14168
135e244776f0
prevent transient leaks of file handle by using new helper functions
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14161
diff
changeset
|
329 for line in self.opener.read('series').splitlines(): |
3714 | 330 if line.startswith('# Merges'): |
331 cur = merges | |
332 continue | |
333 cur.append(revlog.bin(line)) | |
334 | |
335 return (nodes, merges) | |
336 | |
337 def saveseries(self, revmap, merges): | |
338 if not revmap: | |
339 return | |
340 | |
341 if not os.path.isdir(self.path): | |
342 os.mkdir(self.path) | |
343 series = self.opener('series', 'w') | |
8209
a1a5a57efe90
replace util.sort with sorted built-in
Matt Mackall <mpm@selenic.com>
parents:
8176
diff
changeset
|
344 for rev in sorted(revmap): |
3714 | 345 series.write(revlog.hex(revmap[rev]) + '\n') |
346 if merges: | |
347 series.write('# Merges\n') | |
348 for m in merges: | |
349 series.write(revlog.hex(m) + '\n') | |
350 series.close() | |
351 | |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
352 def parselog(self, fp): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
353 parents = [] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
354 message = [] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
355 node = revlog.nullid |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
356 inmsg = False |
13789
7e5031180c0f
transplant: fix crash if filter script munges log file
Luke Plant <L.Plant.98@cantab.net>
parents:
13742
diff
changeset
|
357 user = None |
7e5031180c0f
transplant: fix crash if filter script munges log file
Luke Plant <L.Plant.98@cantab.net>
parents:
13742
diff
changeset
|
358 date = None |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
359 for line in fp.read().splitlines(): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
360 if inmsg: |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
361 message.append(line) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
362 elif line.startswith('# User '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
363 user = line[7:] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
364 elif line.startswith('# Date '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
365 date = line[7:] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
366 elif line.startswith('# Node ID '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
367 node = revlog.bin(line[10:]) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
368 elif line.startswith('# Parent '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
369 parents.append(revlog.bin(line[9:])) |
11411
5834e79b24f7
transplant: when reading journal, treat only lines starting with "# " special like patch.extract() does
Georg Brandl <georg@python.org>
parents:
11321
diff
changeset
|
370 elif not line.startswith('# '): |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
371 inmsg = True |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
372 message.append(line) |
13789
7e5031180c0f
transplant: fix crash if filter script munges log file
Luke Plant <L.Plant.98@cantab.net>
parents:
13742
diff
changeset
|
373 if None in (user, date): |
13790
c0ed76b5056d
Fix transplant error message to correspond with test
Brendan Cully <brendan@kublai.com>
parents:
13789
diff
changeset
|
374 raise util.Abort(_("filter corrupted changeset (no user or date)")) |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
375 return (node, user, date, '\n'.join(message), parents) |
4516
96d8a56d4ef9
Removed trailing whitespace and tabs from python files
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4251
diff
changeset
|
376 |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
377 def log(self, user, date, message, p1, p2, merge=False): |
3714 | 378 '''journal changelog metadata for later recover''' |
379 | |
380 if not os.path.isdir(self.path): | |
381 os.mkdir(self.path) | |
382 fp = self.opener('journal', 'w') | |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
383 fp.write('# User %s\n' % user) |
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
384 fp.write('# Date %s\n' % date) |
3714 | 385 fp.write('# Node ID %s\n' % revlog.hex(p2)) |
386 fp.write('# Parent ' + revlog.hex(p1) + '\n') | |
387 if merge: | |
388 fp.write('# Parent ' + revlog.hex(p2) + '\n') | |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
389 fp.write(message.rstrip() + '\n') |
3714 | 390 fp.close() |
391 | |
392 def readlog(self): | |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
393 return self.parselog(self.opener('journal')) |
3714 | 394 |
395 def unlog(self): | |
396 '''remove changelog journal''' | |
397 absdst = os.path.join(self.path, 'journal') | |
398 if os.path.exists(absdst): | |
399 os.unlink(absdst) | |
400 | |
401 def transplantfilter(self, repo, source, root): | |
402 def matchfn(node): | |
403 if self.applied(repo, node, root): | |
404 return False | |
405 if source.changelog.parents(node)[1] != revlog.nullid: | |
406 return False | |
407 extra = source.changelog.read(node)[5] | |
408 cnode = extra.get('transplant_source') | |
409 if cnode and self.applied(repo, cnode, root): | |
410 return False | |
411 return True | |
412 | |
413 return matchfn | |
414 | |
415 def hasnode(repo, node): | |
416 try: | |
13031
3da456d0c885
code style: prefer 'is' and 'is not' tests with singletons
Martin Geisler <mg@aragost.com>
parents:
12823
diff
changeset
|
417 return repo.changelog.rev(node) is not None |
7633 | 418 except error.RevlogError: |
3714 | 419 return False |
420 | |
421 def browserevs(ui, repo, nodes, opts): | |
422 '''interactively transplant changesets''' | |
423 def browsehelp(ui): | |
10510
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
424 ui.write(_('y: transplant this changeset\n' |
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
425 'n: skip this changeset\n' |
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
426 'm: merge at this changeset\n' |
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
427 'p: show patch\n' |
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
428 'c: commit selected changesets\n' |
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
429 'q: cancel transplant\n' |
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
430 '?: show this help\n')) |
3714 | 431 |
3723
c828fca6f38a
transplant: show_changeset moved to cmdutil
Brendan Cully <brendan@kublai.com>
parents:
3714
diff
changeset
|
432 displayer = cmdutil.show_changeset(ui, repo, opts) |
3714 | 433 transplants = [] |
434 merges = [] | |
435 for node in nodes: | |
7369
87158be081b8
cmdutil: use change contexts for cset-printer and cset-templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7308
diff
changeset
|
436 displayer.show(repo[node]) |
3714 | 437 action = None |
438 while not action: | |
439 action = ui.prompt(_('apply changeset? [ynmpcq?]:')) | |
440 if action == '?': | |
441 browsehelp(ui) | |
442 action = None | |
443 elif action == 'p': | |
444 parent = repo.changelog.parents(node)[0] | |
7308
b6f5490effbf
patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
445 for chunk in patch.diff(repo, parent, node): |
8615
94ca38e63576
use ui instead of repo.ui when the former is in scope
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
446 ui.write(chunk) |
3714 | 447 action = None |
448 elif action not in ('y', 'n', 'm', 'c', 'q'): | |
10510
f77f3383c666
i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10394
diff
changeset
|
449 ui.write(_('no such option\n')) |
3714 | 450 action = None |
451 if action == 'y': | |
452 transplants.append(node) | |
453 elif action == 'm': | |
454 merges.append(node) | |
455 elif action == 'c': | |
456 break | |
457 elif action == 'q': | |
458 transplants = () | |
459 merges = () | |
460 break | |
10152
56284451a22c
Added support for templatevar "footer" to cmdutil.py
Robert Bachmann <rbachm@gmail.com>
parents:
9995
diff
changeset
|
461 displayer.close() |
3714 | 462 return (transplants, merges) |
463 | |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
464 @command('transplant', |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
465 [('s', 'source', '', _('pull patches from REPO'), _('REPO')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
466 ('b', 'branch', [], |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
467 _('pull patches from branch BRANCH'), _('BRANCH')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
468 ('a', 'all', None, _('pull all changesets up to BRANCH')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
469 ('p', 'prune', [], _('skip over REV'), _('REV')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
470 ('m', 'merge', [], _('merge at REV'), _('REV')), |
15220
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
471 ('e', 'edit', False, _('invoke editor on commit messages')), |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
472 ('', 'log', None, _('append transplant info to log message')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
473 ('c', 'continue', None, _('continue last transplant session ' |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
474 'after repair')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
475 ('', 'filter', '', |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
476 _('filter changesets through command'), _('CMD'))], |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
477 _('hg transplant [-s REPO] [-b BRANCH [-a]] [-p REV] ' |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
478 '[-m REV] [REV]...')) |
3714 | 479 def transplant(ui, repo, *revs, **opts): |
480 '''transplant changesets from another branch | |
481 | |
482 Selected changesets will be applied on top of the current working | |
13605
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
483 directory with the log of the original changeset. The changesets |
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
484 are copied and will thus appear twice in the history. Use the |
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
485 rebase extension instead if you want to move a whole branch of |
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
486 unpublished changesets. |
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
487 |
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
488 If --log is specified, log messages will have a comment appended |
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
489 of the form:: |
3714 | 490 |
9200
6b4c527c3d22
transplant: better reST formatting
Martin Geisler <mg@lazybytes.net>
parents:
9196
diff
changeset
|
491 (transplanted from CHANGESETHASH) |
3714 | 492 |
493 You can rewrite the changelog message with the --filter option. | |
8000
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
494 Its argument will be invoked with the current changelog message as |
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
495 $1 and the patch as $2. |
3714 | 496 |
8076
5ec526c1a32f
help texts: write command line switches as -a/--abc
Martin Geisler <mg@lazybytes.net>
parents:
8000
diff
changeset
|
497 If --source/-s is specified, selects changesets from the named |
5ec526c1a32f
help texts: write command line switches as -a/--abc
Martin Geisler <mg@lazybytes.net>
parents:
8000
diff
changeset
|
498 repository. If --branch/-b is specified, selects changesets from |
5ec526c1a32f
help texts: write command line switches as -a/--abc
Martin Geisler <mg@lazybytes.net>
parents:
8000
diff
changeset
|
499 the branch holding the named revision, up to that revision. If |
5ec526c1a32f
help texts: write command line switches as -a/--abc
Martin Geisler <mg@lazybytes.net>
parents:
8000
diff
changeset
|
500 --all/-a is specified, all changesets on the branch will be |
5ec526c1a32f
help texts: write command line switches as -a/--abc
Martin Geisler <mg@lazybytes.net>
parents:
8000
diff
changeset
|
501 transplanted, otherwise you will be prompted to select the |
5ec526c1a32f
help texts: write command line switches as -a/--abc
Martin Geisler <mg@lazybytes.net>
parents:
8000
diff
changeset
|
502 changesets you want. |
3714 | 503 |
13606
1532ed1e50ca
transplant: avoid the word "rebase" when we mean "transplant"
Martin Geisler <mg@lazybytes.net>
parents:
13605
diff
changeset
|
504 :hg:`transplant --branch REVISION --all` will transplant the |
1532ed1e50ca
transplant: avoid the word "rebase" when we mean "transplant"
Martin Geisler <mg@lazybytes.net>
parents:
13605
diff
changeset
|
505 selected branch (up to the named revision) onto your current |
1532ed1e50ca
transplant: avoid the word "rebase" when we mean "transplant"
Martin Geisler <mg@lazybytes.net>
parents:
13605
diff
changeset
|
506 working directory. |
3714 | 507 |
8000
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
508 You can optionally mark selected transplanted changesets as merge |
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
509 changesets. You will not be prompted to transplant any ancestors |
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
510 of a merged transplant, and you can merge descendants of them |
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
511 normally instead of transplanting them. |
3714 | 512 |
11193
687c7d395f20
Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents:
10510
diff
changeset
|
513 If no merges or revisions are provided, :hg:`transplant` will |
687c7d395f20
Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents:
10510
diff
changeset
|
514 start an interactive changeset browser. |
3714 | 515 |
8000
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
516 If a changeset application fails, you can fix the merge by hand |
11193
687c7d395f20
Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents:
10510
diff
changeset
|
517 and then resume where you left off by calling :hg:`transplant |
687c7d395f20
Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents:
10510
diff
changeset
|
518 --continue/-c`. |
3714 | 519 ''' |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
520 def incwalk(repo, csets, match=util.always): |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
521 for node in csets: |
3714 | 522 if match(node): |
523 yield node | |
524 | |
525 def transplantwalk(repo, root, branches, match=util.always): | |
526 if not branches: | |
527 branches = repo.heads() | |
528 ancestors = [] | |
529 for branch in branches: | |
530 ancestors.append(repo.changelog.ancestor(root, branch)) | |
531 for node in repo.changelog.nodesbetween(ancestors, branches)[0]: | |
532 if match(node): | |
533 yield node | |
534 | |
535 def checkopts(opts, revs): | |
536 if opts.get('continue'): | |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10264
diff
changeset
|
537 if opts.get('branch') or opts.get('all') or opts.get('merge'): |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
538 raise util.Abort(_('--continue is incompatible with ' |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
539 'branch, all or merge')) |
3714 | 540 return |
541 if not (opts.get('source') or revs or | |
542 opts.get('merge') or opts.get('branch')): | |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
543 raise util.Abort(_('no source URL, branch tag or revision ' |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
544 'list provided')) |
3714 | 545 if opts.get('all'): |
546 if not opts.get('branch'): | |
547 raise util.Abort(_('--all requires a branch revision')) | |
548 if revs: | |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
549 raise util.Abort(_('--all is incompatible with a ' |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
550 'revision list')) |
3714 | 551 |
552 checkopts(opts, revs) | |
553 | |
554 if not opts.get('log'): | |
555 opts['log'] = ui.config('transplant', 'log') | |
556 if not opts.get('filter'): | |
557 opts['filter'] = ui.config('transplant', 'filter') | |
558 | |
559 tp = transplanter(ui, repo) | |
15220
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
560 if opts.get('edit'): |
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
561 tp.editor = cmdutil.commitforceeditor |
3714 | 562 |
563 p1, p2 = repo.dirstate.parents() | |
8176
2660e7002413
transplant: forbid transplant to nonempty repositories with no working directory.
Brendan Cully <brendan@kublai.com>
parents:
8173
diff
changeset
|
564 if len(repo) > 0 and p1 == revlog.nullid: |
2660e7002413
transplant: forbid transplant to nonempty repositories with no working directory.
Brendan Cully <brendan@kublai.com>
parents:
8173
diff
changeset
|
565 raise util.Abort(_('no revision checked out')) |
3714 | 566 if not opts.get('continue'): |
567 if p2 != revlog.nullid: | |
568 raise util.Abort(_('outstanding uncommitted merges')) | |
569 m, a, r, d = repo.status()[:4] | |
570 if m or a or r or d: | |
571 raise util.Abort(_('outstanding local changes')) | |
572 | |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
573 sourcerepo = opts.get('source') |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
574 if sourcerepo: |
14556
517e1d88bf7e
hg: change various repository() users to use peer() where appropriate
Matt Mackall <mpm@selenic.com>
parents:
14393
diff
changeset
|
575 source = hg.peer(ui, opts, ui.expandpath(sourcerepo)) |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
576 branches = map(source.lookup, opts.get('branch', ())) |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
577 source, csets, cleanupfn = bundlerepo.getremotechanges(ui, repo, source, |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
578 onlyheads=branches, force=True) |
3714 | 579 else: |
580 source = repo | |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
581 branches = map(source.lookup, opts.get('branch', ())) |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
582 cleanupfn = None |
3714 | 583 |
584 try: | |
585 if opts.get('continue'): | |
3724
ea523d6f5f1a
transplant: fix --continue; add --continue test
Brendan Cully <brendan@kublai.com>
parents:
3723
diff
changeset
|
586 tp.resume(repo, source, opts) |
3714 | 587 return |
588 | |
10394
4612cded5176
fix coding style (reported by pylint)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10282
diff
changeset
|
589 tf = tp.transplantfilter(repo, source, p1) |
3714 | 590 if opts.get('prune'): |
591 prune = [source.lookup(r) | |
14319
b33f3e35efb0
scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents:
14308
diff
changeset
|
592 for r in scmutil.revrange(source, opts.get('prune'))] |
3714 | 593 matchfn = lambda x: tf(x) and x not in prune |
594 else: | |
595 matchfn = tf | |
596 merges = map(source.lookup, opts.get('merge', ())) | |
597 revmap = {} | |
598 if revs: | |
14319
b33f3e35efb0
scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents:
14308
diff
changeset
|
599 for r in scmutil.revrange(source, revs): |
3714 | 600 revmap[int(r)] = source.lookup(r) |
601 elif opts.get('all') or not merges: | |
602 if source != repo: | |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
603 alltransplants = incwalk(source, csets, match=matchfn) |
3714 | 604 else: |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
605 alltransplants = transplantwalk(source, p1, branches, |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
606 match=matchfn) |
3714 | 607 if opts.get('all'): |
608 revs = alltransplants | |
609 else: | |
610 revs, newmerges = browserevs(ui, source, alltransplants, opts) | |
611 merges.extend(newmerges) | |
612 for r in revs: | |
613 revmap[source.changelog.rev(r)] = r | |
614 for r in merges: | |
615 revmap[source.changelog.rev(r)] = r | |
616 | |
617 tp.apply(repo, source, revmap, merges, opts) | |
618 finally: | |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
619 if cleanupfn: |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
620 cleanupfn() |
3714 | 621 |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
622 def revsettransplanted(repo, subset, x): |
14211
b00ab6890fe9
transplant: fix revset doc
Idan Kamara <idankk86@gmail.com>
parents:
13606
diff
changeset
|
623 """``transplanted([set])`` |
b00ab6890fe9
transplant: fix revset doc
Idan Kamara <idankk86@gmail.com>
parents:
13606
diff
changeset
|
624 Transplanted changesets in set, or all transplanted changesets. |
12822
f13acb96b2a7
Fix and unify transplant and bookmarks revsets doc registration
Patrick Mezard <pmezard@gmail.com>
parents:
12734
diff
changeset
|
625 """ |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
626 if x: |
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
627 s = revset.getset(repo, subset, x) |
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
628 else: |
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
629 s = subset |
14212
8f551386abf0
transplant: remove unneeded loop over repo in revset
Idan Kamara <idankk86@gmail.com>
parents:
14168
diff
changeset
|
630 return [r for r in s if repo[r].extra().get('transplant_source')] |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
631 |
13689
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
632 def kwtransplanted(repo, ctx, **args): |
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
633 """:transplanted: String. The node identifier of the transplanted |
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
634 changeset if any.""" |
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
635 n = ctx.extra().get('transplant_source') |
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
636 return n and revlog.hex(n) or '' |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
637 |
12822
f13acb96b2a7
Fix and unify transplant and bookmarks revsets doc registration
Patrick Mezard <pmezard@gmail.com>
parents:
12734
diff
changeset
|
638 def extsetup(ui): |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
639 revset.symbols['transplanted'] = revsettransplanted |
13689
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
640 templatekw.keywords['transplanted'] = kwtransplanted |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
641 |
12823
80deae3bc5ea
hggettext: handle i18nfunctions declaration for docstrings translations
Patrick Mezard <pmezard@gmail.com>
parents:
12822
diff
changeset
|
642 # tell hggettext to extract docstrings from these functions: |
13698
f30ce5983896
i18n: register new template keywords for translation
Patrick Mezard <pmezard@gmail.com>
parents:
13689
diff
changeset
|
643 i18nfunctions = [revsettransplanted, kwtransplanted] |