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