Mercurial > hg
annotate hgext/transplant.py @ 36755:ff4bc0ab6740 stable
wireproto: check permissions when executing "batch" command (BC) (SEC)
For as long as the "batch" command has existed (introduced by
bd88561afb4b and first released as part of Mercurial 1.9), that command
(like most wire commands introduced after 2008) lacked an entry in
the hgweb permissions table. And since we don't verify permissions if
an entry is missing from the permissions table, this meant that
executing a command via "batch" would bypass all permissions
checks.
The security implications are significant: a Mercurial HTTP server
would allow writes via "batch" wire protocol commands as long as
the HTTP request were processed by Mercurial and the process running
the Mercurial HTTP server had write access to the repository. The
Mercurial defaults of servers being read-only and the various web.*
config options to define access control were bypassed.
In addition, "batch" could be used to exfiltrate data from servers
that were configured to not allow read access.
Both forms of permissions bypass could be mitigated to some extent
by using HTTP authentication. This would prevent HTTP requests from
hitting Mercurial's server logic. However, any authenticated request
would still be able to bypass permissions checks via "batch" commands.
The easiest exploit was to send "pushkey" commands via "batch" and
modify the state of bookmarks, phases, and obsolescence markers.
However, I suspect a well-crafted HTTP request could trick the server
into running the "unbundle" wire protocol command, effectively
performing a full `hg push` to create new changesets on the remote.
This commit plugs this gaping security hole by having the "batch"
command perform permissions checking on each sub-command that is
being batched. We do this by threading a permissions checking
callable all the way to the protocol handler. The threading is a
bit hacky from a code perspective. But it preserves API compatibility,
which is the proper thing to do on the stable branch.
One of the subtle things we do is assume that a command with an
undefined permission is a "push" command. This is the safest thing to
do from a security perspective: we don't want to take chances that
a command could perform a write even though the server is configured
to not allow writes.
As the test changes demonstrate, it is no longer possible to bypass
permissions via the "batch" wire protocol command.
.. bc::
The "batch" wire protocol command now enforces permissions of
each invoked sub-command. Wire protocol commands must define
their operation type or the "batch" command will assume they
can write data and will prevent their execution on HTTP servers
unless the HTTP request method is POST, the server is configured
to allow pushes, and the (possibly authenticated) HTTP user is
authorized to perform a push.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 20 Feb 2018 18:55:58 -0800 |
parents | 61275d0f6157 |
children | c8e2d6ed1f9e |
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 |
19028
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
10 This extension allows you to transplant changes to another parent revision, |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
11 possibly in another repository. The transplant is done using 'diff' patches. |
3714 | 12 |
8000
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
13 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
|
14 map from a changeset hash to its hash in the source repository. |
3714 | 15 ''' |
28481
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
16 from __future__ import absolute_import |
3714 | 17 |
28481
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
18 import os |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
19 import tempfile |
7629
97253bcb44a8
transplant: move docstrings before imports (see issue1466)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7415
diff
changeset
|
20 from mercurial.i18n import _ |
28481
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
21 from mercurial import ( |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
22 bundlerepo, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
23 cmdutil, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
24 error, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
25 exchange, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
26 hg, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
27 match, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
28 merge, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
29 node as nodemod, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
30 patch, |
30925
82f1ef8b4477
py3: convert the mode argument of os.fdopen to unicodes (2 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29841
diff
changeset
|
31 pycompat, |
28481
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
32 registrar, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
33 revlog, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
34 revset, |
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
35 scmutil, |
31023
aea06029919e
revset: import set classes directly from smartset module
Yuya Nishihara <yuya@tcha.org>
parents:
30925
diff
changeset
|
36 smartset, |
28481
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
37 util, |
31245
c1ebe18d5156
vfs: use 'vfs' module directly in 'hgext.transplant'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31216
diff
changeset
|
38 vfs as vfsmod, |
28481
ec75c94262a5
transplant: use absolute_import
timeless <timeless@mozdev.org>
parents:
28480
diff
changeset
|
39 ) |
7629
97253bcb44a8
transplant: move docstrings before imports (see issue1466)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7415
diff
changeset
|
40 |
16507
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
41 class TransplantError(error.Abort): |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
42 pass |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
43 |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
44 cmdtable = {} |
32337
46ba2cdda476
registrar: move cmdutil.command to registrar module (API)
Yuya Nishihara <yuya@tcha.org>
parents:
31336
diff
changeset
|
45 command = registrar.command(cmdtable) |
29841
d5883fd055c6
extensions: change magic "shipped with hg" string
Augie Fackler <augie@google.com>
parents:
28540
diff
changeset
|
46 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for |
25186
80c5b2666a96
extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents:
24365
diff
changeset
|
47 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
80c5b2666a96
extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents:
24365
diff
changeset
|
48 # be specifying the version(s) of Mercurial they are tested with, or |
80c5b2666a96
extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents:
24365
diff
changeset
|
49 # leave the attribute unspecified. |
29841
d5883fd055c6
extensions: change magic "shipped with hg" string
Augie Fackler <augie@google.com>
parents:
28540
diff
changeset
|
50 testedwith = 'ships-with-hg-core' |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
51 |
34468
7bcce17b87e8
configitems: register the 'transplant.filter' config
Boris Feld <boris.feld@octobus.net>
parents:
32337
diff
changeset
|
52 configtable = {} |
7bcce17b87e8
configitems: register the 'transplant.filter' config
Boris Feld <boris.feld@octobus.net>
parents:
32337
diff
changeset
|
53 configitem = registrar.configitem(configtable) |
7bcce17b87e8
configitems: register the 'transplant.filter' config
Boris Feld <boris.feld@octobus.net>
parents:
32337
diff
changeset
|
54 |
7bcce17b87e8
configitems: register the 'transplant.filter' config
Boris Feld <boris.feld@octobus.net>
parents:
32337
diff
changeset
|
55 configitem('transplant', 'filter', |
7bcce17b87e8
configitems: register the 'transplant.filter' config
Boris Feld <boris.feld@octobus.net>
parents:
32337
diff
changeset
|
56 default=None, |
7bcce17b87e8
configitems: register the 'transplant.filter' config
Boris Feld <boris.feld@octobus.net>
parents:
32337
diff
changeset
|
57 ) |
34469
61275d0f6157
configitems: register the 'transplant.log' config
Boris Feld <boris.feld@octobus.net>
parents:
34468
diff
changeset
|
58 configitem('transplant', 'log', |
61275d0f6157
configitems: register the 'transplant.log' config
Boris Feld <boris.feld@octobus.net>
parents:
34468
diff
changeset
|
59 default=None, |
61275d0f6157
configitems: register the 'transplant.log' config
Boris Feld <boris.feld@octobus.net>
parents:
34468
diff
changeset
|
60 ) |
34468
7bcce17b87e8
configitems: register the 'transplant.filter' config
Boris Feld <boris.feld@octobus.net>
parents:
32337
diff
changeset
|
61 |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8706
diff
changeset
|
62 class transplantentry(object): |
3714 | 63 def __init__(self, lnode, rnode): |
64 self.lnode = lnode | |
65 self.rnode = rnode | |
66 | |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8706
diff
changeset
|
67 class transplants(object): |
3714 | 68 def __init__(self, path=None, transplantfile=None, opener=None): |
69 self.path = path | |
70 self.transplantfile = transplantfile | |
71 self.opener = opener | |
72 | |
73 if not opener: | |
31245
c1ebe18d5156
vfs: use 'vfs' module directly in 'hgext.transplant'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31216
diff
changeset
|
74 self.opener = vfsmod.vfs(self.path) |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
75 self.transplants = {} |
3714 | 76 self.dirty = False |
77 self.read() | |
78 | |
79 def read(self): | |
80 abspath = os.path.join(self.path, self.transplantfile) | |
81 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
|
82 for line in self.opener.read(self.transplantfile).splitlines(): |
3714 | 83 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
|
84 list = self.transplants.setdefault(rnode, []) |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
85 list.append(transplantentry(lnode, rnode)) |
3714 | 86 |
87 def write(self): | |
88 if self.dirty and self.transplantfile: | |
89 if not os.path.isdir(self.path): | |
90 os.mkdir(self.path) | |
91 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
|
92 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
|
93 for t in list: |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
94 l, r = map(nodemod.hex, (t.lnode, t.rnode)) |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
95 fp.write(l + ':' + r + '\n') |
3714 | 96 fp.close() |
97 self.dirty = False | |
98 | |
99 def get(self, rnode): | |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
100 return self.transplants.get(rnode) or [] |
3714 | 101 |
102 def set(self, lnode, rnode): | |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
103 list = self.transplants.setdefault(rnode, []) |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
104 list.append(transplantentry(lnode, rnode)) |
3714 | 105 self.dirty = True |
106 | |
107 def remove(self, transplant): | |
12313
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
108 list = self.transplants.get(transplant.rnode) |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
109 if list: |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
110 del list[list.index(transplant)] |
2912881c2a98
transplant: maintain list of transplants in dict
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
12266
diff
changeset
|
111 self.dirty = True |
3714 | 112 |
8778
c5f36402daad
use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
8706
diff
changeset
|
113 class transplanter(object): |
21411
afff78be4361
transplant: use "getcommiteditor()" instead of explicit editor choice
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20988
diff
changeset
|
114 def __init__(self, ui, repo, opts): |
3714 | 115 self.ui = ui |
31336
0199686a1a1c
transplant: directly use repo.vfs.join
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31245
diff
changeset
|
116 self.path = repo.vfs.join('transplant') |
31245
c1ebe18d5156
vfs: use 'vfs' module directly in 'hgext.transplant'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31216
diff
changeset
|
117 self.opener = vfsmod.vfs(self.path) |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
118 self.transplants = transplants(self.path, 'transplants', |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
119 opener=self.opener) |
22252
de783f2403c4
transplant: change "editform" to distinguish merge commits from others
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
22006
diff
changeset
|
120 def getcommiteditor(): |
de783f2403c4
transplant: change "editform" to distinguish merge commits from others
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
22006
diff
changeset
|
121 editform = cmdutil.mergeeditform(repo[None], 'transplant') |
de783f2403c4
transplant: change "editform" to distinguish merge commits from others
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
22006
diff
changeset
|
122 return cmdutil.getcommiteditor(editform=editform, **opts) |
de783f2403c4
transplant: change "editform" to distinguish merge commits from others
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
22006
diff
changeset
|
123 self.getcommiteditor = getcommiteditor |
3714 | 124 |
125 def applied(self, repo, node, parent): | |
126 '''returns True if a node is already an ancestor of parent | |
17010
a6c64211acdb
transplant: convert applied() algorithm from nodes to revs
Joshua Redstone <joshua.redstone@fb.com>
parents:
17009
diff
changeset
|
127 or is parent or has already been transplanted''' |
a6c64211acdb
transplant: convert applied() algorithm from nodes to revs
Joshua Redstone <joshua.redstone@fb.com>
parents:
17009
diff
changeset
|
128 if hasnode(repo, parent): |
a6c64211acdb
transplant: convert applied() algorithm from nodes to revs
Joshua Redstone <joshua.redstone@fb.com>
parents:
17009
diff
changeset
|
129 parentrev = repo.changelog.rev(parent) |
3714 | 130 if hasnode(repo, node): |
17010
a6c64211acdb
transplant: convert applied() algorithm from nodes to revs
Joshua Redstone <joshua.redstone@fb.com>
parents:
17009
diff
changeset
|
131 rev = repo.changelog.rev(node) |
18082
40f0c0748cfc
transplant: replace incancestors uses with ancestors
Siddharth Agarwal <sid0@fb.com>
parents:
17874
diff
changeset
|
132 reachable = repo.changelog.ancestors([parentrev], rev, |
40f0c0748cfc
transplant: replace incancestors uses with ancestors
Siddharth Agarwal <sid0@fb.com>
parents:
17874
diff
changeset
|
133 inclusive=True) |
17010
a6c64211acdb
transplant: convert applied() algorithm from nodes to revs
Joshua Redstone <joshua.redstone@fb.com>
parents:
17009
diff
changeset
|
134 if rev in reachable: |
3714 | 135 return True |
136 for t in self.transplants.get(node): | |
137 # it might have been stripped | |
138 if not hasnode(repo, t.lnode): | |
139 self.transplants.remove(t) | |
140 return False | |
17010
a6c64211acdb
transplant: convert applied() algorithm from nodes to revs
Joshua Redstone <joshua.redstone@fb.com>
parents:
17009
diff
changeset
|
141 lnoderev = repo.changelog.rev(t.lnode) |
18082
40f0c0748cfc
transplant: replace incancestors uses with ancestors
Siddharth Agarwal <sid0@fb.com>
parents:
17874
diff
changeset
|
142 if lnoderev in repo.changelog.ancestors([parentrev], lnoderev, |
40f0c0748cfc
transplant: replace incancestors uses with ancestors
Siddharth Agarwal <sid0@fb.com>
parents:
17874
diff
changeset
|
143 inclusive=True): |
3714 | 144 return True |
145 return False | |
146 | |
26346
2449a0a6ebda
transplant: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25879
diff
changeset
|
147 def apply(self, repo, source, revmap, merges, opts=None): |
3714 | 148 '''apply the revisions in revmap one by one in revision order''' |
26346
2449a0a6ebda
transplant: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25879
diff
changeset
|
149 if opts is None: |
2449a0a6ebda
transplant: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25879
diff
changeset
|
150 opts = {} |
8209
a1a5a57efe90
replace util.sort with sorted built-in
Matt Mackall <mpm@selenic.com>
parents:
8176
diff
changeset
|
151 revs = sorted(revmap) |
3714 | 152 p1, p2 = repo.dirstate.parents() |
153 pulls = [] | |
23452
86c0d8c1484f
transplant: don't honor whitespace and format-changing diffopts
Siddharth Agarwal <sid0@fb.com>
parents:
23270
diff
changeset
|
154 diffopts = patch.difffeatureopts(self.ui, opts) |
3714 | 155 diffopts.git = True |
156 | |
27289
ee33e677f0ac
transplant: widen wlock scope of transplant for consitency while processing
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
157 lock = tr = None |
3714 | 158 try: |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
159 lock = repo.lock() |
15204
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
160 tr = repo.transaction('transplant') |
3714 | 161 for rev in revs: |
162 node = revmap[rev] | |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
163 revstr = '%s:%s' % (rev, nodemod.short(node)) |
3714 | 164 |
165 if self.applied(repo, node, p1): | |
166 self.ui.warn(_('skipping already applied revision %s\n') % | |
167 revstr) | |
168 continue | |
169 | |
170 parents = source.changelog.parents(node) | |
16627
38c45a99be0b
transplant: manually transplant pullable changesets with --log
Levi Bard <levi@unity3d.com>
parents:
16551
diff
changeset
|
171 if not (opts.get('filter') or opts.get('log')): |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
172 # If the changeset parent is the same as the |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
173 # wdir's parent, just pull it. |
3714 | 174 if parents[0] == p1: |
175 pulls.append(node) | |
176 p1 = node | |
177 continue | |
178 if pulls: | |
179 if source != repo: | |
22699
74da54e52d7c
transplant: use exchange.pull
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
22252
diff
changeset
|
180 exchange.pull(repo, source.peer(), heads=pulls) |
27344
43c00ca887d1
merge: have merge.update use a matcher instead of partial fn
Augie Fackler <augie@google.com>
parents:
27322
diff
changeset
|
181 merge.update(repo, pulls[-1], False, False) |
3714 | 182 p1, p2 = repo.dirstate.parents() |
183 pulls = [] | |
184 | |
185 domerge = False | |
186 if node in merges: | |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
187 # 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
|
188 # couldn't transplant after the latest even if |
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
189 # transplants before them fail. |
3714 | 190 domerge = True |
191 if not hasnode(repo, node): | |
22699
74da54e52d7c
transplant: use exchange.pull
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
22252
diff
changeset
|
192 exchange.pull(repo, source.peer(), heads=[node]) |
3714 | 193 |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
194 skipmerge = False |
3714 | 195 if parents[1] != revlog.nullid: |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
196 if not opts.get('parent'): |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
197 self.ui.note(_('skipping merge changeset %s:%s\n') |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
198 % (rev, nodemod.short(node))) |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
199 skipmerge = True |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
200 else: |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
201 parent = source.lookup(opts['parent']) |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
202 if parent not in parents: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
203 raise error.Abort(_('%s is not a parent of %s') % |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
204 (nodemod.short(parent), |
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
205 nodemod.short(node))) |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
206 else: |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
207 parent = parents[0] |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
208 |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
209 if skipmerge: |
3714 | 210 patchfile = None |
211 else: | |
212 fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-') | |
30925
82f1ef8b4477
py3: convert the mode argument of os.fdopen to unicodes (2 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29841
diff
changeset
|
213 fp = os.fdopen(fd, pycompat.sysstr('w')) |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
214 gen = patch.diff(source, parent, node, opts=diffopts) |
7308
b6f5490effbf
patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
215 for chunk in gen: |
b6f5490effbf
patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
216 fp.write(chunk) |
3714 | 217 fp.close() |
218 | |
219 del revmap[rev] | |
220 if patchfile or domerge: | |
221 try: | |
16507
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
222 try: |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
223 n = self.applyone(repo, node, |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
224 source.changelog.read(node), |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
225 patchfile, merge=domerge, |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
226 log=opts.get('log'), |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
227 filter=opts.get('filter')) |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
228 except TransplantError: |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
229 # Do not rollback, it is up to the user to |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
230 # fix the merge or cancel everything |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
231 tr.close() |
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
232 raise |
4251
e76e52145c3d
transplant: fix ignoring empty changesets (eg after filter)
Brendan Cully <brendan@kublai.com>
parents:
4072
diff
changeset
|
233 if n and domerge: |
3714 | 234 self.ui.status(_('%s merged at %s\n') % (revstr, |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
235 nodemod.short(n))) |
4251
e76e52145c3d
transplant: fix ignoring empty changesets (eg after filter)
Brendan Cully <brendan@kublai.com>
parents:
4072
diff
changeset
|
236 elif n: |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
237 self.ui.status(_('%s transplanted to %s\n') |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
238 % (nodemod.short(node), |
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
239 nodemod.short(n))) |
3714 | 240 finally: |
241 if patchfile: | |
242 os.unlink(patchfile) | |
15204
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
243 tr.close() |
3714 | 244 if pulls: |
22699
74da54e52d7c
transplant: use exchange.pull
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
22252
diff
changeset
|
245 exchange.pull(repo, source.peer(), heads=pulls) |
27344
43c00ca887d1
merge: have merge.update use a matcher instead of partial fn
Augie Fackler <augie@google.com>
parents:
27322
diff
changeset
|
246 merge.update(repo, pulls[-1], False, False) |
3714 | 247 finally: |
248 self.saveseries(revmap, merges) | |
249 self.transplants.write() | |
15204
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
250 if tr: |
3ce9b1a7538b
transplant: wrap a transaction around the whole command
Greg Ward <greg@gerg.ca>
parents:
14741
diff
changeset
|
251 tr.release() |
25879
99e88320d665
transplant: restore dirstate correctly at unexpected failure
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
25828
diff
changeset
|
252 if lock: |
99e88320d665
transplant: restore dirstate correctly at unexpected failure
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
25828
diff
changeset
|
253 lock.release() |
3714 | 254 |
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
|
255 def filter(self, filter, node, changelog, patchfile): |
3714 | 256 '''arbitrarily rewrite changeset before applying it''' |
257 | |
6966
057ced2b8543
i18n: mark strings for translation in transplant extension
Martin Geisler <mg@daimi.au.dk>
parents:
6762
diff
changeset
|
258 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
|
259 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
|
260 fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-') |
30925
82f1ef8b4477
py3: convert the mode argument of os.fdopen to unicodes (2 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29841
diff
changeset
|
261 fp = os.fdopen(fd, pycompat.sysstr('w')) |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
262 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
|
263 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
|
264 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
|
265 fp.write(msg + '\n') |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
266 fp.close() |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
267 |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
268 try: |
23270
41c03b7592ed
util.system: use ui.system() in place of optional ui.fout parameter
Yuya Nishihara <yuya@tcha.org>
parents:
22699
diff
changeset
|
269 self.ui.system('%s %s %s' % (filter, util.shellquote(headerfile), |
41c03b7592ed
util.system: use ui.system() in place of optional ui.fout parameter
Yuya Nishihara <yuya@tcha.org>
parents:
22699
diff
changeset
|
270 util.shellquote(patchfile)), |
41c03b7592ed
util.system: use ui.system() in place of optional ui.fout parameter
Yuya Nishihara <yuya@tcha.org>
parents:
22699
diff
changeset
|
271 environ={'HGUSER': changelog[1], |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
272 'HGREVISION': nodemod.hex(node), |
23270
41c03b7592ed
util.system: use ui.system() in place of optional ui.fout parameter
Yuya Nishihara <yuya@tcha.org>
parents:
22699
diff
changeset
|
273 }, |
31202
2db38ef73ce8
transplant: set a blockedtag when invoking external filter
Simon Farnsworth <simonfar@fb.com>
parents:
31023
diff
changeset
|
274 onerr=error.Abort, errprefix=_('filter failed'), |
2db38ef73ce8
transplant: set a blockedtag when invoking external filter
Simon Farnsworth <simonfar@fb.com>
parents:
31023
diff
changeset
|
275 blockedtag='transplant_filter') |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
276 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
|
277 finally: |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
278 os.unlink(headerfile) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
279 |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
280 return (user, date, msg) |
3714 | 281 |
282 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
|
283 filter=None): |
3714 | 284 '''apply the patch in patchfile to the repository as a transplant''' |
285 (manifest, user, (time, timezone), files, message) = cl[:5] | |
286 date = "%d %d" % (time, timezone) | |
287 extra = {'transplant_source': node} | |
288 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
|
289 (user, date, message) = self.filter(filter, node, cl, patchfile) |
3714 | 290 |
291 if log: | |
9183
d0225fa2f6c4
do not translate commit messages
Martin Geisler <mg@lazybytes.net>
parents:
8934
diff
changeset
|
292 # we don't translate messages inserted into commits |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
293 message += '\n(transplanted from %s)' % nodemod.hex(node) |
3714 | 294 |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
295 self.ui.status(_('applying %s\n') % nodemod.short(node)) |
3714 | 296 self.ui.note('%s %s\n%s\n' % (user, date, message)) |
297 | |
298 if not patchfile and not merge: | |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
299 raise error.Abort(_('can only omit patchfile if merging')) |
3714 | 300 if patchfile: |
301 try: | |
14564
65f4512e40e4
patch: turn patch() touched files dict into a set
Patrick Mezard <pmezard@gmail.com>
parents:
14556
diff
changeset
|
302 files = set() |
14382
2d16f15da7bd
patch: remove patch.patch() cwd argument
Patrick Mezard <pmezard@gmail.com>
parents:
14319
diff
changeset
|
303 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
|
304 files = list(files) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25186
diff
changeset
|
305 except Exception as inst: |
3757
faed44bab17b
transplant: clobber old series when transplant fails
Brendan Cully <brendan@kublai.com>
parents:
3752
diff
changeset
|
306 seriespath = os.path.join(self.path, 'series') |
faed44bab17b
transplant: clobber old series when transplant fails
Brendan Cully <brendan@kublai.com>
parents:
3752
diff
changeset
|
307 if os.path.exists(seriespath): |
faed44bab17b
transplant: clobber old series when transplant fails
Brendan Cully <brendan@kublai.com>
parents:
3752
diff
changeset
|
308 os.unlink(seriespath) |
13878
a8d13ee0ce68
misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents:
13790
diff
changeset
|
309 p1 = repo.dirstate.p1() |
3714 | 310 p2 = node |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
311 self.log(user, date, message, p1, p2, merge=merge) |
3714 | 312 self.ui.write(str(inst) + '\n') |
27676
1c48f348f2d0
transplant: correct language to use working directory
timeless <timeless@mozdev.org>
parents:
27586
diff
changeset
|
313 raise TransplantError(_('fix up the working directory and run ' |
16507
1f020021adfa
transplant: do not rollback on patching error (issue3379)
Patrick Mezard <patrick@mezard.eu>
parents:
16457
diff
changeset
|
314 'hg transplant --continue')) |
3714 | 315 else: |
316 files = None | |
317 if merge: | |
318 p1, p2 = repo.dirstate.parents() | |
16551
ebf6d38c9063
localrepo: add setparents() to adjust dirstate copies (issue3407)
Patrick Mezard <patrick@mezard.eu>
parents:
16507
diff
changeset
|
319 repo.setparents(p1, node) |
8703
8676dd819444
transplant: use match object rather than files for commit
Matt Mackall <mpm@selenic.com>
parents:
8615
diff
changeset
|
320 m = match.always(repo.root, '') |
8676dd819444
transplant: use match object rather than files for commit
Matt Mackall <mpm@selenic.com>
parents:
8615
diff
changeset
|
321 else: |
8676dd819444
transplant: use match object rather than files for commit
Matt Mackall <mpm@selenic.com>
parents:
8615
diff
changeset
|
322 m = match.exact(repo.root, '', files) |
3714 | 323 |
15220
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
324 n = repo.commit(message, user, date, extra=extra, match=m, |
22252
de783f2403c4
transplant: change "editform" to distinguish merge commits from others
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
22006
diff
changeset
|
325 editor=self.getcommiteditor()) |
11638
79231258503b
transplant: crash if repo.commit() finds nothing to commit
Greg Ward <greg-hg@gerg.ca>
parents:
11411
diff
changeset
|
326 if not n: |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
327 self.ui.warn(_('skipping emptied changeset %s\n') % |
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
328 nodemod.short(node)) |
17319
a189d4470a34
transplant: handle non-empty patches doing nothing (issue2806)
Patrick Mezard <patrick@mezard.eu>
parents:
17299
diff
changeset
|
329 return None |
3714 | 330 if not merge: |
331 self.transplants.set(n, node) | |
332 | |
333 return n | |
334 | |
27677
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
335 def canresume(self): |
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
336 return os.path.exists(os.path.join(self.path, 'journal')) |
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
337 |
18919
cdf764a2f7a5
repoview: remove unreachable code
Bryan O'Sullivan <bryano@fb.com>
parents:
18082
diff
changeset
|
338 def resume(self, repo, source, opts): |
3714 | 339 '''recover last transaction and apply remaining changesets''' |
340 if os.path.exists(os.path.join(self.path, 'journal')): | |
18926
8deaa703a622
transplant: pass source through to recover
Bryan O'Sullivan <bryano@fb.com>
parents:
18919
diff
changeset
|
341 n, node = self.recover(repo, source, opts) |
23781
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
342 if n: |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
343 self.ui.status(_('%s transplanted as %s\n') % |
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
344 (nodemod.short(node), |
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
345 nodemod.short(n))) |
23781
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
346 else: |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
347 self.ui.status(_('%s skipped due to empty diff\n') |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
348 % (nodemod.short(node),)) |
3714 | 349 seriespath = os.path.join(self.path, 'series') |
350 if not os.path.exists(seriespath): | |
3758
889f7e74a0d9
transplant: log source node when recovering too.
Brendan Cully <brendan@kublai.com>
parents:
3757
diff
changeset
|
351 self.transplants.write() |
3714 | 352 return |
353 nodes, merges = self.readseries() | |
354 revmap = {} | |
355 for n in nodes: | |
356 revmap[source.changelog.rev(n)] = n | |
357 os.unlink(seriespath) | |
358 | |
359 self.apply(repo, source, revmap, merges, opts) | |
360 | |
18926
8deaa703a622
transplant: pass source through to recover
Bryan O'Sullivan <bryano@fb.com>
parents:
18919
diff
changeset
|
361 def recover(self, repo, source, opts): |
3714 | 362 '''commit working directory using journal metadata''' |
363 node, user, date, message, parents = self.readlog() | |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
364 merge = False |
3714 | 365 |
366 if not user or not date or not message or not parents[0]: | |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
367 raise error.Abort(_('transplant log file is corrupt')) |
3714 | 368 |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
369 parent = parents[0] |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
370 if len(parents) > 1: |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
371 if opts.get('parent'): |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
372 parent = source.lookup(opts['parent']) |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
373 if parent not in parents: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
374 raise error.Abort(_('%s is not a parent of %s') % |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
375 (nodemod.short(parent), |
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
376 nodemod.short(node))) |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
377 else: |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
378 merge = True |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
379 |
3758
889f7e74a0d9
transplant: log source node when recovering too.
Brendan Cully <brendan@kublai.com>
parents:
3757
diff
changeset
|
380 extra = {'transplant_source': node} |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
381 try: |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
382 p1, p2 = repo.dirstate.parents() |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
383 if p1 != parent: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
384 raise error.Abort(_('working directory not at transplant ' |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
385 'parent %s') % nodemod.hex(parent)) |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
386 if merge: |
16551
ebf6d38c9063
localrepo: add setparents() to adjust dirstate copies (issue3407)
Patrick Mezard <patrick@mezard.eu>
parents:
16507
diff
changeset
|
387 repo.setparents(p1, parents[1]) |
23781
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
388 modified, added, removed, deleted = repo.status()[:4] |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
389 if merge or modified or added or removed or deleted: |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
390 n = repo.commit(message, user, date, extra=extra, |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
391 editor=self.getcommiteditor()) |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
392 if not n: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
393 raise error.Abort(_('commit failed')) |
23781
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
394 if not merge: |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
395 self.transplants.set(n, node) |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
396 else: |
49caef455912
transplant: properly skip empty changeset (issue4423)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23452
diff
changeset
|
397 n = None |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
398 self.unlog() |
3714 | 399 |
4915
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
400 return n, node |
97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents:
4680
diff
changeset
|
401 finally: |
27289
ee33e677f0ac
transplant: widen wlock scope of transplant for consitency while processing
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
402 # TODO: get rid of this meaningless try/finally enclosing. |
ee33e677f0ac
transplant: widen wlock scope of transplant for consitency while processing
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
403 # this is kept only to reduce changes in a patch. |
ee33e677f0ac
transplant: widen wlock scope of transplant for consitency while processing
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
404 pass |
3714 | 405 |
406 def readseries(self): | |
407 nodes = [] | |
408 merges = [] | |
409 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
|
410 for line in self.opener.read('series').splitlines(): |
3714 | 411 if line.startswith('# Merges'): |
412 cur = merges | |
413 continue | |
414 cur.append(revlog.bin(line)) | |
415 | |
416 return (nodes, merges) | |
417 | |
418 def saveseries(self, revmap, merges): | |
419 if not revmap: | |
420 return | |
421 | |
422 if not os.path.isdir(self.path): | |
423 os.mkdir(self.path) | |
424 series = self.opener('series', 'w') | |
8209
a1a5a57efe90
replace util.sort with sorted built-in
Matt Mackall <mpm@selenic.com>
parents:
8176
diff
changeset
|
425 for rev in sorted(revmap): |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
426 series.write(nodemod.hex(revmap[rev]) + '\n') |
3714 | 427 if merges: |
428 series.write('# Merges\n') | |
429 for m in merges: | |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
430 series.write(nodemod.hex(m) + '\n') |
3714 | 431 series.close() |
432 | |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
433 def parselog(self, fp): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
434 parents = [] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
435 message = [] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
436 node = revlog.nullid |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
437 inmsg = False |
13789
7e5031180c0f
transplant: fix crash if filter script munges log file
Luke Plant <L.Plant.98@cantab.net>
parents:
13742
diff
changeset
|
438 user = None |
7e5031180c0f
transplant: fix crash if filter script munges log file
Luke Plant <L.Plant.98@cantab.net>
parents:
13742
diff
changeset
|
439 date = None |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
440 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
|
441 if inmsg: |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
442 message.append(line) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
443 elif line.startswith('# User '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
444 user = line[7:] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
445 elif line.startswith('# Date '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
446 date = line[7:] |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
447 elif line.startswith('# Node ID '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
448 node = revlog.bin(line[10:]) |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
449 elif line.startswith('# Parent '): |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
450 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
|
451 elif not line.startswith('# '): |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
452 inmsg = True |
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
453 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
|
454 if None in (user, date): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
455 raise error.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
|
456 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
|
457 |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
458 def log(self, user, date, message, p1, p2, merge=False): |
3714 | 459 '''journal changelog metadata for later recover''' |
460 | |
461 if not os.path.isdir(self.path): | |
462 os.mkdir(self.path) | |
463 fp = self.opener('journal', 'w') | |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
464 fp.write('# User %s\n' % user) |
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
465 fp.write('# Date %s\n' % date) |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
466 fp.write('# Node ID %s\n' % nodemod.hex(p2)) |
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
467 fp.write('# Parent ' + nodemod.hex(p1) + '\n') |
3714 | 468 if merge: |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
469 fp.write('# Parent ' + nodemod.hex(p2) + '\n') |
3725
ccc7a9eb0e5e
transplant: preserve filter changes in --continue log
Brendan Cully <brendan@kublai.com>
parents:
3724
diff
changeset
|
470 fp.write(message.rstrip() + '\n') |
3714 | 471 fp.close() |
472 | |
473 def readlog(self): | |
3759
e96f97ca0358
transplant: split filter args into changelog entry and patch
Brendan Cully <brendan@kublai.com>
parents:
3758
diff
changeset
|
474 return self.parselog(self.opener('journal')) |
3714 | 475 |
476 def unlog(self): | |
477 '''remove changelog journal''' | |
478 absdst = os.path.join(self.path, 'journal') | |
479 if os.path.exists(absdst): | |
480 os.unlink(absdst) | |
481 | |
482 def transplantfilter(self, repo, source, root): | |
483 def matchfn(node): | |
484 if self.applied(repo, node, root): | |
485 return False | |
486 if source.changelog.parents(node)[1] != revlog.nullid: | |
487 return False | |
488 extra = source.changelog.read(node)[5] | |
489 cnode = extra.get('transplant_source') | |
490 if cnode and self.applied(repo, cnode, root): | |
491 return False | |
492 return True | |
493 | |
494 return matchfn | |
495 | |
496 def hasnode(repo, node): | |
497 try: | |
13031
3da456d0c885
code style: prefer 'is' and 'is not' tests with singletons
Martin Geisler <mg@aragost.com>
parents:
12823
diff
changeset
|
498 return repo.changelog.rev(node) is not None |
7633 | 499 except error.RevlogError: |
3714 | 500 return False |
501 | |
502 def browserevs(ui, repo, nodes, opts): | |
503 '''interactively transplant changesets''' | |
3723
c828fca6f38a
transplant: show_changeset moved to cmdutil
Brendan Cully <brendan@kublai.com>
parents:
3714
diff
changeset
|
504 displayer = cmdutil.show_changeset(ui, repo, opts) |
3714 | 505 transplants = [] |
506 merges = [] | |
20268
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
507 prompt = _('apply changeset? [ynmpcq?]:' |
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
508 '$$ &yes, transplant this changeset' |
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
509 '$$ &no, skip this changeset' |
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
510 '$$ &merge at this changeset' |
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
511 '$$ show &patch' |
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
512 '$$ &commit selected changesets' |
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
513 '$$ &quit and cancel transplant' |
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
514 '$$ &? (show this help)') |
3714 | 515 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
|
516 displayer.show(repo[node]) |
3714 | 517 action = None |
518 while not action: | |
20268
27d3f1fe42ac
transplant: use "ui.promptchoice()" for interactive transplant
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20020
diff
changeset
|
519 action = 'ynmpcq?'[ui.promptchoice(prompt)] |
3714 | 520 if action == '?': |
20269
acb6cceaffd5
transplant: use "ui.extractchoices()" to show the list of available responses
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20268
diff
changeset
|
521 for c, t in ui.extractchoices(prompt)[1]: |
acb6cceaffd5
transplant: use "ui.extractchoices()" to show the list of available responses
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20268
diff
changeset
|
522 ui.write('%s: %s\n' % (c, t)) |
3714 | 523 action = None |
524 elif action == 'p': | |
525 parent = repo.changelog.parents(node)[0] | |
7308
b6f5490effbf
patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
526 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
|
527 ui.write(chunk) |
3714 | 528 action = None |
529 if action == 'y': | |
530 transplants.append(node) | |
531 elif action == 'm': | |
532 merges.append(node) | |
533 elif action == 'c': | |
534 break | |
535 elif action == 'q': | |
536 transplants = () | |
537 merges = () | |
538 break | |
10152
56284451a22c
Added support for templatevar "footer" to cmdutil.py
Robert Bachmann <rbachm@gmail.com>
parents:
9995
diff
changeset
|
539 displayer.close() |
3714 | 540 return (transplants, merges) |
541 | |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
542 @command('transplant', |
19028
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
543 [('s', 'source', '', _('transplant changesets from REPO'), _('REPO')), |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
544 ('b', 'branch', [], _('use this source changeset as head'), _('REV')), |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
545 ('a', 'all', None, _('pull all changesets up to the --branch revisions')), |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
546 ('p', 'prune', [], _('skip over REV'), _('REV')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
547 ('m', 'merge', [], _('merge at REV'), _('REV')), |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
548 ('', 'parent', '', |
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
549 _('parent to choose when transplanting merge'), _('REV')), |
15220
f7db54b832af
transplant: add --edit option
Matt Mackall <mpm@selenic.com>
parents:
15204
diff
changeset
|
550 ('e', 'edit', False, _('invoke editor on commit messages')), |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
551 ('', 'log', None, _('append transplant info to log message')), |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
552 ('c', 'continue', None, _('continue last transplant session ' |
19028
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
553 'after fixing conflicts')), |
14308
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
554 ('', 'filter', '', |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
555 _('filter changesets through command'), _('CMD'))], |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
556 _('hg transplant [-s REPO] [-b BRANCH [-a]] [-p REV] ' |
e7ea3e38fea8
transplant: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents:
14260
diff
changeset
|
557 '[-m REV] [REV]...')) |
3714 | 558 def transplant(ui, repo, *revs, **opts): |
559 '''transplant changesets from another branch | |
560 | |
561 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
|
562 directory with the log of the original changeset. The changesets |
19028
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
563 are copied and will thus appear twice in the history with different |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
564 identities. |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
565 |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
566 Consider using the graft command if everything is inside the same |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
567 repository - it will use merges and will usually give a better result. |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
568 Use the rebase extension if the changesets are unpublished and you want |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
569 to move them instead of copying them. |
13605
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
570 |
888ec2650c2d
transplant: explain that changesets are copied, not moved
Martin Geisler <mg@lazybytes.net>
parents:
13031
diff
changeset
|
571 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
|
572 of the form:: |
3714 | 573 |
9200
6b4c527c3d22
transplant: better reST formatting
Martin Geisler <mg@lazybytes.net>
parents:
9196
diff
changeset
|
574 (transplanted from CHANGESETHASH) |
3714 | 575 |
576 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
|
577 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
|
578 $1 and the patch as $2. |
3714 | 579 |
19028
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
580 --source/-s specifies another repository to use for selecting changesets, |
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
581 just as if it temporarily had been pulled. |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
582 If --branch/-b is specified, these revisions will be used as |
19951
d51c4d85ec23
spelling: random spell checker fixes
Mads Kiilerich <madski@unity3d.com>
parents:
19496
diff
changeset
|
583 heads when deciding which changesets to transplant, just as if only |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
584 these revisions had been pulled. |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
585 If --all/-a is specified, all the revisions up to the heads specified |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
586 with --branch will be transplanted. |
3714 | 587 |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
588 Example: |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
589 |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
590 - transplant all changes up to REV on top of your current revision:: |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
591 |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
592 hg transplant --branch REV --all |
3714 | 593 |
8000
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
594 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
|
595 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
|
596 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
|
597 normally instead of transplanting them. |
3714 | 598 |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
599 Merge changesets may be transplanted directly by specifying the |
16457
91196ebcaeed
transplant: remove extraneous whitespace
Steven Stallion <sstallion@gmail.com>
parents:
16400
diff
changeset
|
600 proper parent changeset by calling :hg:`transplant --parent`. |
16400
f2ba409dbb0f
transplant: permit merge changesets via --parent
Steven Stallion <sstallion@gmail.com>
parents:
15220
diff
changeset
|
601 |
11193
687c7d395f20
Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents:
10510
diff
changeset
|
602 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
|
603 start an interactive changeset browser. |
3714 | 604 |
8000
83d7c9cfb065
transplant: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents:
7874
diff
changeset
|
605 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
|
606 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
|
607 --continue/-c`. |
3714 | 608 ''' |
27840
dc237afacbd4
with: use context manager for wlock in transplant
Bryan O'Sullivan <bryano@fb.com>
parents:
27678
diff
changeset
|
609 with repo.wlock(): |
27289
ee33e677f0ac
transplant: widen wlock scope of transplant for consitency while processing
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
610 return _dotransplant(ui, repo, *revs, **opts) |
ee33e677f0ac
transplant: widen wlock scope of transplant for consitency while processing
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
611 |
ee33e677f0ac
transplant: widen wlock scope of transplant for consitency while processing
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
612 def _dotransplant(ui, repo, *revs, **opts): |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
613 def incwalk(repo, csets, match=util.always): |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
614 for node in csets: |
3714 | 615 if match(node): |
616 yield node | |
617 | |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
618 def transplantwalk(repo, dest, heads, match=util.always): |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
619 '''Yield all nodes that are ancestors of a head but not ancestors |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
620 of dest. |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
621 If no heads are specified, the heads of repo will be used.''' |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
622 if not heads: |
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
623 heads = repo.heads() |
3714 | 624 ancestors = [] |
20988
8c2f1e2a11ff
transplant: use context ancestor instead of changelog ancestor
Mads Kiilerich <madski@unity3d.com>
parents:
20442
diff
changeset
|
625 ctx = repo[dest] |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
626 for head in heads: |
20988
8c2f1e2a11ff
transplant: use context ancestor instead of changelog ancestor
Mads Kiilerich <madski@unity3d.com>
parents:
20442
diff
changeset
|
627 ancestors.append(ctx.ancestor(repo[head]).node()) |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
628 for node in repo.changelog.nodesbetween(ancestors, heads)[0]: |
3714 | 629 if match(node): |
630 yield node | |
631 | |
632 def checkopts(opts, revs): | |
633 if opts.get('continue'): | |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10264
diff
changeset
|
634 if opts.get('branch') or opts.get('all') or opts.get('merge'): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
635 raise error.Abort(_('--continue is incompatible with ' |
19028
b512934988d4
transplant: improve documentation
Mads Kiilerich <madski@unity3d.com>
parents:
19027
diff
changeset
|
636 '--branch, --all and --merge')) |
3714 | 637 return |
638 if not (opts.get('source') or revs or | |
639 opts.get('merge') or opts.get('branch')): | |
27322
84e85f461b79
transplant: use Oxford comma
timeless <timeless@mozdev.org>
parents:
27289
diff
changeset
|
640 raise error.Abort(_('no source URL, branch revision, or revision ' |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
641 'list provided')) |
3714 | 642 if opts.get('all'): |
643 if not opts.get('branch'): | |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
644 raise error.Abort(_('--all requires a branch revision')) |
3714 | 645 if revs: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
646 raise error.Abort(_('--all is incompatible with a ' |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
647 'revision list')) |
3714 | 648 |
649 checkopts(opts, revs) | |
650 | |
651 if not opts.get('log'): | |
25828
5ae4b128a291
transplant: mark some undocumented options deprecated
Matt Mackall <mpm@selenic.com>
parents:
25695
diff
changeset
|
652 # deprecated config: transplant.log |
3714 | 653 opts['log'] = ui.config('transplant', 'log') |
654 if not opts.get('filter'): | |
25828
5ae4b128a291
transplant: mark some undocumented options deprecated
Matt Mackall <mpm@selenic.com>
parents:
25695
diff
changeset
|
655 # deprecated config: transplant.filter |
3714 | 656 opts['filter'] = ui.config('transplant', 'filter') |
657 | |
21411
afff78be4361
transplant: use "getcommiteditor()" instead of explicit editor choice
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20988
diff
changeset
|
658 tp = transplanter(ui, repo, opts) |
3714 | 659 |
660 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
|
661 if len(repo) > 0 and p1 == revlog.nullid: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
662 raise error.Abort(_('no revision checked out')) |
27677
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
663 if opts.get('continue'): |
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
664 if not tp.canresume(): |
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
665 raise error.Abort(_('no transplant to continue')) |
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
666 else: |
128ef8828ed5
transplant: only use checkunfinished if not continue
timeless <timeless@mozdev.org>
parents:
27676
diff
changeset
|
667 cmdutil.checkunfinished(repo) |
3714 | 668 if p2 != revlog.nullid: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
669 raise error.Abort(_('outstanding uncommitted merges')) |
3714 | 670 m, a, r, d = repo.status()[:4] |
671 if m or a or r or d: | |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26578
diff
changeset
|
672 raise error.Abort(_('outstanding local changes')) |
3714 | 673 |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
674 sourcerepo = opts.get('source') |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
675 if sourcerepo: |
17874
2ba70eec1cf0
peer: subrepo isolation, pass repo instead of repo.ui to hg.peer
Simon Heimberg <simohe@besonet.ch>
parents:
17320
diff
changeset
|
676 peer = hg.peer(repo, opts, ui.expandpath(sourcerepo)) |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
677 heads = map(peer.lookup, opts.get('branch', ())) |
25679
540cd0ddac49
transplant: only pull the transplanted revision (issue4692)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
24365
diff
changeset
|
678 target = set(heads) |
540cd0ddac49
transplant: only pull the transplanted revision (issue4692)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
24365
diff
changeset
|
679 for r in revs: |
540cd0ddac49
transplant: only pull the transplanted revision (issue4692)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
24365
diff
changeset
|
680 try: |
540cd0ddac49
transplant: only pull the transplanted revision (issue4692)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
24365
diff
changeset
|
681 target.add(peer.lookup(r)) |
540cd0ddac49
transplant: only pull the transplanted revision (issue4692)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
24365
diff
changeset
|
682 except error.RepoError: |
540cd0ddac49
transplant: only pull the transplanted revision (issue4692)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
24365
diff
changeset
|
683 pass |
17191
5884812686f7
peer: introduce peer methods to prepare for peer classes
Sune Foldager <cryo@cyanite.org>
parents:
17010
diff
changeset
|
684 source, csets, cleanupfn = bundlerepo.getremotechanges(ui, repo, peer, |
25679
540cd0ddac49
transplant: only pull the transplanted revision (issue4692)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
24365
diff
changeset
|
685 onlyheads=sorted(target), force=True) |
3714 | 686 else: |
687 source = repo | |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
688 heads = map(source.lookup, opts.get('branch', ())) |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
689 cleanupfn = None |
3714 | 690 |
691 try: | |
692 if opts.get('continue'): | |
3724
ea523d6f5f1a
transplant: fix --continue; add --continue test
Brendan Cully <brendan@kublai.com>
parents:
3723
diff
changeset
|
693 tp.resume(repo, source, opts) |
3714 | 694 return |
695 | |
10394
4612cded5176
fix coding style (reported by pylint)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10282
diff
changeset
|
696 tf = tp.transplantfilter(repo, source, p1) |
3714 | 697 if opts.get('prune'): |
19055
0fc41f88f148
transplant: use set for prune lookup
Mads Kiilerich <madski@unity3d.com>
parents:
19028
diff
changeset
|
698 prune = set(source.lookup(r) |
0fc41f88f148
transplant: use set for prune lookup
Mads Kiilerich <madski@unity3d.com>
parents:
19028
diff
changeset
|
699 for r in scmutil.revrange(source, opts.get('prune'))) |
3714 | 700 matchfn = lambda x: tf(x) and x not in prune |
701 else: | |
702 matchfn = tf | |
703 merges = map(source.lookup, opts.get('merge', ())) | |
704 revmap = {} | |
705 if revs: | |
14319
b33f3e35efb0
scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents:
14308
diff
changeset
|
706 for r in scmutil.revrange(source, revs): |
3714 | 707 revmap[int(r)] = source.lookup(r) |
708 elif opts.get('all') or not merges: | |
709 if source != repo: | |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
710 alltransplants = incwalk(source, csets, match=matchfn) |
3714 | 711 else: |
19027
3f5fac4b1cfa
transplant: clarify what --branch do - it has nothing to do with branches
Mads Kiilerich <madski@unity3d.com>
parents:
18926
diff
changeset
|
712 alltransplants = transplantwalk(source, p1, heads, |
7744
b44dbb95f07f
transplant: wrapped long lines
Martin Geisler <mg@daimi.au.dk>
parents:
7633
diff
changeset
|
713 match=matchfn) |
3714 | 714 if opts.get('all'): |
715 revs = alltransplants | |
716 else: | |
717 revs, newmerges = browserevs(ui, source, alltransplants, opts) | |
718 merges.extend(newmerges) | |
719 for r in revs: | |
720 revmap[source.changelog.rev(r)] = r | |
721 for r in merges: | |
722 revmap[source.changelog.rev(r)] = r | |
723 | |
724 tp.apply(repo, source, revmap, merges, opts) | |
725 finally: | |
14161
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
726 if cleanupfn: |
8a0fca925992
bundlerepo: fix and improve getremotechanges
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
14073
diff
changeset
|
727 cleanupfn() |
3714 | 728 |
28394
dcb4209bd30d
revset: replace extpredicate by revsetpredicate of registrar
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
27840
diff
changeset
|
729 revsetpredicate = registrar.revsetpredicate() |
27586
42910f9fffeb
revset: use delayregistrar to register predicate in extension easily
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
27344
diff
changeset
|
730 |
42910f9fffeb
revset: use delayregistrar to register predicate in extension easily
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
27344
diff
changeset
|
731 @revsetpredicate('transplanted([set])') |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
732 def revsettransplanted(repo, subset, x): |
27586
42910f9fffeb
revset: use delayregistrar to register predicate in extension easily
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
27344
diff
changeset
|
733 """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
|
734 """ |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
735 if x: |
17299
e51d4aedace9
check-code: indent 4 spaces in py files
Mads Kiilerich <mads@kiilerich.com>
parents:
17191
diff
changeset
|
736 s = revset.getset(repo, subset, x) |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
737 else: |
17299
e51d4aedace9
check-code: indent 4 spaces in py files
Mads Kiilerich <mads@kiilerich.com>
parents:
17191
diff
changeset
|
738 s = subset |
31023
aea06029919e
revset: import set classes directly from smartset module
Yuya Nishihara <yuya@tcha.org>
parents:
30925
diff
changeset
|
739 return smartset.baseset([r for r in s if |
20442
8524cdf66a12
hgext: updated extensions to return a baseset when adding symbols
Lucas Moscovicz <lmoscovicz@fb.com>
parents:
20269
diff
changeset
|
740 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
|
741 |
28540
012411b9940d
hgext: use templatekeyword to mark a function as template keyword
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
28481
diff
changeset
|
742 templatekeyword = registrar.templatekeyword() |
012411b9940d
hgext: use templatekeyword to mark a function as template keyword
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
28481
diff
changeset
|
743 |
012411b9940d
hgext: use templatekeyword to mark a function as template keyword
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
28481
diff
changeset
|
744 @templatekeyword('transplanted') |
13689
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
745 def kwtransplanted(repo, ctx, **args): |
28540
012411b9940d
hgext: use templatekeyword to mark a function as template keyword
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
28481
diff
changeset
|
746 """String. The node identifier of the transplanted |
13689
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
747 changeset if any.""" |
65399579da68
transplant: add "transplanted" keyword
Patrick Mezard <pmezard@gmail.com>
parents:
13607
diff
changeset
|
748 n = ctx.extra().get('transplant_source') |
28480
db171c6a1697
transplant: switch to using nodemod for hex+short
timeless <timeless@mozdev.org>
parents:
28394
diff
changeset
|
749 return n and nodemod.hex(n) or '' |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
750 |
12822
f13acb96b2a7
Fix and unify transplant and bookmarks revsets doc registration
Patrick Mezard <pmezard@gmail.com>
parents:
12734
diff
changeset
|
751 def extsetup(ui): |
19480
7c0bb2b75aa8
transplant: add checkunfinished (issue3955)
Matt Mackall <mpm@selenic.com>
parents:
19055
diff
changeset
|
752 cmdutil.unfinishedstates.append( |
27678
b97004648028
transplant: specify the right file and path for unfinishedstates
timeless <timeless@mozdev.org>
parents:
27677
diff
changeset
|
753 ['transplant/journal', True, False, _('transplant in progress'), |
19480
7c0bb2b75aa8
transplant: add checkunfinished (issue3955)
Matt Mackall <mpm@selenic.com>
parents:
19055
diff
changeset
|
754 _("use 'hg transplant --continue' or 'hg update' to abort")]) |
12581
19dabc8a3236
transplant: add the transplanted revset predicate
Juan Pablo Aroztegi <juanpablo.aroztegi@openbravo.com>
parents:
12349
diff
changeset
|
755 |
12823
80deae3bc5ea
hggettext: handle i18nfunctions declaration for docstrings translations
Patrick Mezard <pmezard@gmail.com>
parents:
12822
diff
changeset
|
756 # 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
|
757 i18nfunctions = [revsettransplanted, kwtransplanted] |