Mercurial > hg
annotate hgext/split.py @ 43254:181d28ba05da
copies: avoid instancing more changectx to access parent revisions
We just need to know the revision numbers of the parents, creating full context
is needlessly expensive.
This provide a small, but noticeable performance boost.
revision: large amount; added files: large amount; rename small amount; c3b14617fbd7 9ba6ab77fd29
before: ! wall 2.885636 comb 2.900000 user 2.870000 sys 0.030000 (median of 10)
after: ! wall 2.702270 comb 2.710000 user 2.690000 sys 0.020000 (median of 10)
revision: large amount; added files: small amount; rename small amount; c3b14617fbd7 f650a9b140d2
before: ! wall 4.298271 comb 4.290000 user 4.240000 sys 0.050000 (median of 10)
after: ! wall 3.976610 comb 3.970000 user 3.920000 sys 0.050000 (median of 10)
revision: large amount; added files: large amount; rename large amount; 08ea3258278e d9fa043f30c0
before: ! wall 0.773397 comb 0.770000 user 0.770000 sys 0.000000 (median of 11)
after: ! wall 0.701634 comb 0.700000 user 0.700000 sys 0.000000 (median of 13)
revision: small amount; added files: large amount; rename large amount; df6f7a526b60 a83dc6a2d56f
before: ! wall 0.013585 comb 0.010000 user 0.010000 sys 0.000000 (median of 217)
after: ! wall 0.013550 comb 0.010000 user 0.010000 sys 0.000000 (median of 218)
revision: small amount; added files: large amount; rename small amount; 4aa4e1f8e19a 169138063d63
before: ! wall 0.003202 comb 0.000000 user 0.000000 sys 0.000000 (median of 929)
after: ! wall 0.002993 comb 0.010000 user 0.010000 sys 0.000000 (median of 992)
revision: small amount; added files: small amount; rename small amount; 4bc173b045a6 964879152e2e
before: ! wall 0.000077 comb 0.000000 user 0.000000 sys 0.000000 (median of 12060)
after: ! wall 0.000072 comb 0.000000 user 0.000000 sys 0.000000 (median of 12804)
revision: medium amount; added files: large amount; rename medium amount; c95f1ced15f2 2c68e87c3efe
before: ! wall 0.510614 comb 0.500000 user 0.500000 sys 0.000000 (median of 18)
after: ! wall 0.473681 comb 0.470000 user 0.470000 sys 0.000000 (median of 20)
revision: medium amount; added files: medium amount; rename small amount; d343da0c55a8 d7746d32bf9d
before: ! wall 0.126552 comb 0.130000 user 0.130000 sys 0.000000 (median of 77)
after: ! wall 0.115240 comb 0.110000 user 0.110000 sys 0.000000 (median of 85)
Differential Revision: https://phab.mercurial-scm.org/D7122
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Wed, 16 Oct 2019 17:49:30 +0200 |
parents | 8ff1ecfadcd1 |
children | 705738def50c |
rev | line source |
---|---|
35455 | 1 # split.py - split a changeset into smaller ones |
2 # | |
3 # Copyright 2015 Laurent Charignon <lcharignon@fb.com> | |
4 # Copyright 2017 Facebook, Inc. | |
5 # | |
6 # This software may be used and distributed according to the terms of the | |
7 # GNU General Public License version 2 or any later version. | |
8 """command to split a changeset into smaller ones (EXPERIMENTAL)""" | |
9 | |
10 from __future__ import absolute_import | |
11 | |
12 from mercurial.i18n import _ | |
13 | |
14 from mercurial.node import ( | |
15 nullid, | |
16 short, | |
17 ) | |
18 | |
19 from mercurial import ( | |
20 bookmarks, | |
21 cmdutil, | |
22 commands, | |
23 error, | |
24 hg, | |
25 obsolete, | |
26 phases, | |
36400
7b86aa31b004
py3: fix handling of keyword arguments at more places
Pulkit Goyal <7895pulkit@gmail.com>
parents:
35455
diff
changeset
|
27 pycompat, |
35455 | 28 registrar, |
29 revsetlang, | |
30 scmutil, | |
31 ) | |
32 | |
33 # allow people to use split without explicitly enabling rebase extension | |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
34 from . import rebase |
35455 | 35 |
36 cmdtable = {} | |
37 command = registrar.command(cmdtable) | |
38 | |
39 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | |
40 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | |
41 # be specifying the version(s) of Mercurial they are tested with, or | |
42 # leave the attribute unspecified. | |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
43 testedwith = b'ships-with-hg-core' |
35455 | 44 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
45 |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
46 @command( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
47 b'split', |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
48 [ |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
49 (b'r', b'rev', b'', _(b"revision to split"), _(b'REV')), |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
50 (b'', b'rebase', True, _(b'rebase descendants after split')), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
51 ] |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
52 + cmdutil.commitopts2, |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
53 _(b'hg split [--no-rebase] [[-r] REV]'), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
54 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
55 helpbasic=True, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
56 ) |
35455 | 57 def split(ui, repo, *revs, **opts): |
58 """split a changeset into smaller ones | |
59 | |
60 Repeatedly prompt changes and commit message for new changesets until there | |
61 is nothing left in the original changeset. | |
62 | |
63 If --rev was not given, split the working directory parent. | |
64 | |
65 By default, rebase connected non-obsoleted descendants onto the new | |
66 changeset. Use --no-rebase to avoid the rebase. | |
67 """ | |
38069
5ba0cf22e4d0
py3: fix kwargs handling in hgext/split.py
Pulkit Goyal <7895pulkit@gmail.com>
parents:
36408
diff
changeset
|
68 opts = pycompat.byteskwargs(opts) |
35455 | 69 revlist = [] |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
70 if opts.get(b'rev'): |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
71 revlist.append(opts.get(b'rev')) |
35455 | 72 revlist.extend(revs) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
73 with repo.wlock(), repo.lock(), repo.transaction(b'split') as tr: |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
74 revs = scmutil.revrange(repo, revlist or [b'.']) |
35455 | 75 if len(revs) > 1: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
76 raise error.Abort(_(b'cannot split multiple revisions')) |
35455 | 77 |
78 rev = revs.first() | |
79 ctx = repo[rev] | |
80 if rev is None or ctx.node() == nullid: | |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
81 ui.status(_(b'nothing to split\n')) |
35455 | 82 return 1 |
83 if ctx.node() is None: | |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
84 raise error.Abort(_(b'cannot split working directory')) |
35455 | 85 |
86 # rewriteutil.precheck is not very useful here because: | |
87 # 1. null check is done above and it's more friendly to return 1 | |
88 # instead of abort | |
89 # 2. mergestate check is done below by cmdutil.bailifchanged | |
90 # 3. unstable check is more complex here because of --rebase | |
91 # | |
92 # So only "public" check is useful and it's checked directly here. | |
93 if ctx.phase() == phases.public: | |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
94 raise error.Abort( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
95 _(b'cannot split public changeset'), |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
96 hint=_(b"see 'hg help phases' for details"), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
97 ) |
35455 | 98 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
99 descendants = list(repo.revs(b'(%d::) - (%d)', rev, rev)) |
35455 | 100 alloworphaned = obsolete.isenabled(repo, obsolete.allowunstableopt) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
101 if opts.get(b'rebase'): |
35455 | 102 # Skip obsoleted descendants and their descendants so the rebase |
103 # won't cause conflicts for sure. | |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
104 torebase = list( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
105 repo.revs( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
106 b'%ld - (%ld & obsolete())::', descendants, descendants |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
107 ) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
108 ) |
35455 | 109 if not alloworphaned and len(torebase) != len(descendants): |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
110 raise error.Abort( |
43117
8ff1ecfadcd1
cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents:
43077
diff
changeset
|
111 _(b'split would leave orphaned changesets behind') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
112 ) |
35455 | 113 else: |
114 if not alloworphaned and descendants: | |
115 raise error.Abort( | |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
116 _(b'cannot split changeset with children without rebase') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
117 ) |
35455 | 118 torebase = () |
119 | |
120 if len(ctx.parents()) > 1: | |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
121 raise error.Abort(_(b'cannot split a merge changeset')) |
35455 | 122 |
123 cmdutil.bailifchanged(repo) | |
124 | |
125 # Deactivate bookmark temporarily so it won't get moved unintentionally | |
126 bname = repo._activebookmark | |
127 if bname and repo._bookmarks[bname] != ctx.node(): | |
128 bookmarks.deactivate(repo) | |
129 | |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
130 wnode = repo[b'.'].node() |
35455 | 131 top = None |
132 try: | |
133 top = dosplit(ui, repo, tr, ctx, opts) | |
134 finally: | |
135 # top is None: split failed, need update --clean recovery. | |
136 # wnode == ctx.node(): wnode split, no need to update. | |
137 if top is None or wnode != ctx.node(): | |
138 hg.clean(repo, wnode, show_stats=False) | |
139 if bname: | |
140 bookmarks.activate(repo, bname) | |
141 if torebase and top: | |
142 dorebase(ui, repo, torebase, top) | |
143 | |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
144 |
35455 | 145 def dosplit(ui, repo, tr, ctx, opts): |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
146 committed = [] # [ctx] |
35455 | 147 |
148 # Set working parent to ctx.p1(), and keep working copy as ctx's content | |
41966
42e2c7c52e1b
split: use the new movedirstate() we now have in scmutil
Martin von Zweigbergk <martinvonz@google.com>
parents:
40295
diff
changeset
|
149 if ctx.node() != repo.dirstate.p1(): |
42e2c7c52e1b
split: use the new movedirstate() we now have in scmutil
Martin von Zweigbergk <martinvonz@google.com>
parents:
40295
diff
changeset
|
150 hg.clean(repo, ctx.node(), show_stats=False) |
42e2c7c52e1b
split: use the new movedirstate() we now have in scmutil
Martin von Zweigbergk <martinvonz@google.com>
parents:
40295
diff
changeset
|
151 with repo.dirstate.parentchange(): |
42e2c7c52e1b
split: use the new movedirstate() we now have in scmutil
Martin von Zweigbergk <martinvonz@google.com>
parents:
40295
diff
changeset
|
152 scmutil.movedirstate(repo, ctx.p1()) |
35455 | 153 |
154 # Any modified, added, removed, deleted result means split is incomplete | |
155 incomplete = lambda repo: any(repo.status()[:4]) | |
156 | |
157 # Main split loop | |
158 while incomplete(repo): | |
159 if committed: | |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
160 header = _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
161 b'HG: Splitting %s. So far it has been split into:\n' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
162 ) % short(ctx.node()) |
35455 | 163 for c in committed: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
164 firstline = c.description().split(b'\n', 1)[0] |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
165 header += _(b'HG: - %s: %s\n') % (short(c.node()), firstline) |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
166 header += _( |
43117
8ff1ecfadcd1
cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents:
43077
diff
changeset
|
167 b'HG: Write commit message for the next split changeset.\n' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
168 ) |
35455 | 169 else: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
170 header = _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
171 b'HG: Splitting %s. Write commit message for the ' |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
172 b'first split changeset.\n' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
173 ) % short(ctx.node()) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
174 opts.update( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
175 { |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
176 b'edit': True, |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
177 b'interactive': True, |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
178 b'message': header + ctx.description(), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
179 } |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
180 ) |
36400
7b86aa31b004
py3: fix handling of keyword arguments at more places
Pulkit Goyal <7895pulkit@gmail.com>
parents:
35455
diff
changeset
|
181 commands.commit(ui, repo, **pycompat.strkwargs(opts)) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
182 newctx = repo[b'.'] |
35455 | 183 committed.append(newctx) |
184 | |
185 if not committed: | |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
186 raise error.Abort(_(b'cannot split an empty revision')) |
35455 | 187 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
188 scmutil.cleanupnodes( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
189 repo, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
190 {ctx.node(): [c.node() for c in committed]}, |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
191 operation=b'split', |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
192 fixphase=True, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
193 ) |
35455 | 194 |
195 return committed[-1] | |
196 | |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
197 |
36408
83bade6206d4
split: use ctx.rev() instead of %d % ctx
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
198 def dorebase(ui, repo, src, destctx): |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
199 rebase.rebase( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
200 ui, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
201 repo, |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
202 rev=[revsetlang.formatspec(b'%ld', src)], |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
203 dest=revsetlang.formatspec(b'%d', destctx.rev()), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
41966
diff
changeset
|
204 ) |