##// END OF EJS Templates
rewriteutil: fix crash when a rewritten message references f{6,64}...
Augie Fackler -
r48591:48da5c32 stable
parent child Browse files
Show More
@@ -1,247 +1,252 b''
1 1 # rewriteutil.py - utility functions for rewriting changesets
2 2 #
3 3 # Copyright 2017 Octobus <contact@octobus.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import re
11 11
12 12 from .i18n import _
13 13 from .node import (
14 14 hex,
15 15 nullrev,
16 16 )
17 17
18 18 from . import (
19 19 error,
20 20 node,
21 21 obsolete,
22 22 obsutil,
23 23 revset,
24 24 scmutil,
25 25 util,
26 26 )
27 27
28 28
29 29 NODE_RE = re.compile(br'\b[0-9a-f]{6,64}\b')
30 30
31 31
32 32 def _formatrevs(repo, revs, maxrevs=4):
33 33 """returns a string summarizing revisions in a decent size
34 34
35 35 If there are few enough revisions, we list them all. Otherwise we display a
36 36 summary of the form:
37 37
38 38 1ea73414a91b and 5 others
39 39 """
40 40 tonode = repo.changelog.node
41 41 numrevs = len(revs)
42 42 if numrevs < maxrevs:
43 43 shorts = [node.short(tonode(r)) for r in revs]
44 44 summary = b', '.join(shorts)
45 45 else:
46 46 first = revs.first()
47 47 summary = _(b'%s and %d others')
48 48 summary %= (node.short(tonode(first)), numrevs - 1)
49 49 return summary
50 50
51 51
52 52 def precheck(repo, revs, action=b'rewrite'):
53 53 """check if revs can be rewritten
54 54 action is used to control the error message.
55 55
56 56 Make sure this function is called after taking the lock.
57 57 """
58 58 if nullrev in revs:
59 59 msg = _(b"cannot %s the null revision") % action
60 60 hint = _(b"no changeset checked out")
61 61 raise error.InputError(msg, hint=hint)
62 62
63 63 if any(util.safehasattr(r, 'rev') for r in revs):
64 64 repo.ui.develwarn(b"rewriteutil.precheck called with ctx not revs")
65 65 revs = (r.rev() for r in revs)
66 66
67 67 if len(repo[None].parents()) > 1:
68 68 raise error.StateError(
69 69 _(b"cannot %s changesets while merging") % action
70 70 )
71 71
72 72 publicrevs = repo.revs(b'%ld and public()', revs)
73 73 if publicrevs:
74 74 summary = _formatrevs(repo, publicrevs)
75 75 msg = _(b"cannot %s public changesets: %s") % (action, summary)
76 76 hint = _(b"see 'hg help phases' for details")
77 77 raise error.InputError(msg, hint=hint)
78 78
79 79 newunstable = disallowednewunstable(repo, revs)
80 80 if newunstable:
81 81 hint = _(b"see 'hg help evolution.instability'")
82 82 raise error.InputError(
83 83 _(b"cannot %s changeset, as that will orphan %d descendants")
84 84 % (action, len(newunstable)),
85 85 hint=hint,
86 86 )
87 87
88 88 if not obsolete.isenabled(repo, obsolete.allowdivergenceopt):
89 89 new_divergence = _find_new_divergence(repo, revs)
90 90 if new_divergence:
91 91 local_ctx, other_ctx, base_ctx = new_divergence
92 92 msg = _(
93 93 b'cannot %s %s, as that creates content-divergence with %s'
94 94 ) % (
95 95 action,
96 96 local_ctx,
97 97 other_ctx,
98 98 )
99 99 if local_ctx.rev() != base_ctx.rev():
100 100 msg += _(b', from %s') % base_ctx
101 101 if repo.ui.verbose:
102 102 if local_ctx.rev() != base_ctx.rev():
103 103 msg += _(
104 104 b'\n changeset %s is a successor of ' b'changeset %s'
105 105 ) % (local_ctx, base_ctx)
106 106 msg += _(
107 107 b'\n changeset %s already has a successor in '
108 108 b'changeset %s\n'
109 109 b' rewriting changeset %s would create '
110 110 b'"content-divergence"\n'
111 111 b' set experimental.evolution.allowdivergence=True to '
112 112 b'skip this check'
113 113 ) % (base_ctx, other_ctx, local_ctx)
114 114 raise error.InputError(
115 115 msg,
116 116 hint=_(
117 117 b"see 'hg help evolution.instability' for details on content-divergence"
118 118 ),
119 119 )
120 120 else:
121 121 raise error.InputError(
122 122 msg,
123 123 hint=_(
124 124 b"add --verbose for details or see "
125 125 b"'hg help evolution.instability'"
126 126 ),
127 127 )
128 128
129 129
130 130 def disallowednewunstable(repo, revs):
131 131 """Checks whether editing the revs will create new unstable changesets and
132 132 are we allowed to create them.
133 133
134 134 To allow new unstable changesets, set the config:
135 135 `experimental.evolution.allowunstable=True`
136 136 """
137 137 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
138 138 if allowunstable:
139 139 return revset.baseset()
140 140 return repo.revs(b"(%ld::) - %ld", revs, revs)
141 141
142 142
143 143 def _find_new_divergence(repo, revs):
144 144 obsrevs = repo.revs(b'%ld and obsolete()', revs)
145 145 for r in obsrevs:
146 146 div = find_new_divergence_from(repo, repo[r])
147 147 if div:
148 148 return (repo[r], repo[div[0]], repo.unfiltered()[div[1]])
149 149 return None
150 150
151 151
152 152 def find_new_divergence_from(repo, ctx):
153 153 """return divergent revision if rewriting an obsolete cset (ctx) will
154 154 create divergence
155 155
156 156 Returns (<other node>, <common ancestor node>) or None
157 157 """
158 158 if not ctx.obsolete():
159 159 return None
160 160 # We need to check two cases that can cause divergence:
161 161 # case 1: the rev being rewritten has a non-obsolete successor (easily
162 162 # detected by successorssets)
163 163 sset = obsutil.successorssets(repo, ctx.node())
164 164 if sset:
165 165 return (sset[0][0], ctx.node())
166 166 else:
167 167 # case 2: one of the precursors of the rev being revived has a
168 168 # non-obsolete successor (we need divergentsets for this)
169 169 divsets = obsutil.divergentsets(repo, ctx)
170 170 if divsets:
171 171 nsuccset = divsets[0][b'divergentnodes']
172 172 prec = divsets[0][b'commonpredecessor']
173 173 return (nsuccset[0], prec)
174 174 return None
175 175
176 176
177 177 def skip_empty_successor(ui, command):
178 178 empty_successor = ui.config(b'rewrite', b'empty-successor')
179 179 if empty_successor == b'skip':
180 180 return True
181 181 elif empty_successor == b'keep':
182 182 return False
183 183 else:
184 184 raise error.ConfigError(
185 185 _(
186 186 b"%s doesn't know how to handle config "
187 187 b"rewrite.empty-successor=%s (only 'skip' and 'keep' are "
188 188 b"supported)"
189 189 )
190 190 % (command, empty_successor)
191 191 )
192 192
193 193
194 194 def update_hash_refs(repo, commitmsg, pending=None):
195 195 """Replace all obsolete commit hashes in the message with the current hash.
196 196
197 197 If the obsolete commit was split or is divergent, the hash is not replaced
198 198 as there's no way to know which successor to choose.
199 199
200 200 For commands that update a series of commits in the current transaction, the
201 201 new obsolete markers can be considered by setting ``pending`` to a mapping
202 202 of ``pending[oldnode] = [successor_node1, successor_node2,..]``.
203 203 """
204 204 if not pending:
205 205 pending = {}
206 206 cache = {}
207 207 hashes = re.findall(NODE_RE, commitmsg)
208 208 unfi = repo.unfiltered()
209 209 for h in hashes:
210 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
210 try:
211 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
212 except error.WdirUnsupported:
213 # Someone has an fffff... in a commit message we're
214 # rewriting. Don't try rewriting that.
215 continue
211 216 if fullnode is None:
212 217 continue
213 218 ctx = unfi[fullnode]
214 219 if not ctx.obsolete():
215 220 successors = pending.get(fullnode)
216 221 if successors is None:
217 222 continue
218 223 # obsutil.successorssets() returns a list of list of nodes
219 224 successors = [successors]
220 225 else:
221 226 successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
222 227
223 228 # We can't make any assumptions about how to update the hash if the
224 229 # cset in question was split or diverged.
225 230 if len(successors) == 1 and len(successors[0]) == 1:
226 231 successor = successors[0][0]
227 232 if successor is not None:
228 233 newhash = hex(successor)
229 234 commitmsg = commitmsg.replace(h, newhash[: len(h)])
230 235 else:
231 236 repo.ui.note(
232 237 _(
233 238 b'The stale commit message reference to %s could '
234 239 b'not be updated\n(The referenced commit was dropped)\n'
235 240 )
236 241 % h
237 242 )
238 243 else:
239 244 repo.ui.note(
240 245 _(
241 246 b'The stale commit message reference to %s could '
242 247 b'not be updated\n'
243 248 )
244 249 % h
245 250 )
246 251
247 252 return commitmsg
@@ -1,1022 +1,1022 b''
1 1 #require symlink execbit
2 2 $ cat << EOF >> $HGRCPATH
3 3 > [phases]
4 4 > publish=False
5 5 > [extensions]
6 6 > amend=
7 7 > rebase=
8 8 > debugdrawdag=$TESTDIR/drawdag.py
9 9 > strip=
10 10 > [rebase]
11 11 > experimental.inmemory=1
12 12 > [diff]
13 13 > git=1
14 14 > [alias]
15 15 > tglog = log -G --template "{rev}: {node|short} '{desc}'\n"
16 16 > EOF
17 17
18 18 Rebase a simple DAG:
19 19 $ hg init repo1
20 20 $ cd repo1
21 21 $ hg debugdrawdag <<'EOS'
22 22 > c b
23 23 > |/
24 24 > d
25 25 > |
26 26 > a
27 27 > EOS
28 28 $ hg up -C a
29 29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 30 $ hg tglog
31 31 o 3: 814f6bd05178 'c'
32 32 |
33 33 | o 2: db0e82a16a62 'b'
34 34 |/
35 35 o 1: 02952614a83d 'd'
36 36 |
37 37 @ 0: b173517d0057 'a'
38 38
39 39 $ hg cat -r 3 c
40 40 c (no-eol)
41 41 $ hg cat -r 2 b
42 42 b (no-eol)
43 43 $ hg rebase --debug -r b -d c | grep rebasing
44 44 rebasing in memory
45 45 rebasing 2:db0e82a16a62 b "b"
46 46 $ hg tglog
47 47 o 3: ca58782ad1e4 'b'
48 48 |
49 49 o 2: 814f6bd05178 'c'
50 50 |
51 51 o 1: 02952614a83d 'd'
52 52 |
53 53 @ 0: b173517d0057 'a'
54 54
55 55 $ hg cat -r 3 b
56 56 b (no-eol)
57 57 $ hg cat -r 2 c
58 58 c (no-eol)
59 59 $ cd ..
60 60
61 61 Case 2:
62 62 $ hg init repo2
63 63 $ cd repo2
64 64 $ hg debugdrawdag <<'EOS'
65 65 > c b
66 66 > |/
67 67 > d
68 68 > |
69 69 > a
70 70 > EOS
71 71
72 72 Add a symlink and executable file:
73 73 $ hg up -C c
74 74 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 75 $ ln -s somefile e
76 76 $ echo f > f
77 77 $ chmod +x f
78 78 $ hg add e f
79 79 $ hg amend -q
80 80 $ hg up -Cq a
81 81
82 82 Write files to the working copy, and ensure they're still there after the rebase
83 83 $ echo "abc" > a
84 84 $ ln -s def b
85 85 $ echo "ghi" > c
86 86 $ echo "jkl" > d
87 87 $ echo "mno" > e
88 88 $ hg tglog
89 89 o 3: f56b71190a8f 'c'
90 90 |
91 91 | o 2: db0e82a16a62 'b'
92 92 |/
93 93 o 1: 02952614a83d 'd'
94 94 |
95 95 @ 0: b173517d0057 'a'
96 96
97 97 $ hg cat -r 3 c
98 98 c (no-eol)
99 99 $ hg cat -r 2 b
100 100 b (no-eol)
101 101 $ hg cat -r 3 e
102 102 somefile (no-eol)
103 103 $ hg rebase --debug -s b -d a | grep rebasing
104 104 rebasing in memory
105 105 rebasing 2:db0e82a16a62 b "b"
106 106 $ hg tglog
107 107 o 3: fc055c3b4d33 'b'
108 108 |
109 109 | o 2: f56b71190a8f 'c'
110 110 | |
111 111 | o 1: 02952614a83d 'd'
112 112 |/
113 113 @ 0: b173517d0057 'a'
114 114
115 115 $ hg cat -r 2 c
116 116 c (no-eol)
117 117 $ hg cat -r 3 b
118 118 b (no-eol)
119 119 $ hg rebase --debug -s 1 -d 3 | grep rebasing
120 120 rebasing in memory
121 121 rebasing 1:02952614a83d d "d"
122 122 rebasing 2:f56b71190a8f "c"
123 123 $ hg tglog
124 124 o 3: 753feb6fd12a 'c'
125 125 |
126 126 o 2: 09c044d2cb43 'd'
127 127 |
128 128 o 1: fc055c3b4d33 'b'
129 129 |
130 130 @ 0: b173517d0057 'a'
131 131
132 132 Ensure working copy files are still there:
133 133 $ cat a
134 134 abc
135 135 $ readlink.py b
136 136 b -> def
137 137 $ cat e
138 138 mno
139 139
140 140 Ensure symlink and executable files were rebased properly:
141 141 $ hg up -Cq 3
142 142 $ readlink.py e
143 143 e -> somefile
144 144 $ ls -l f | cut -c -10
145 145 -rwxr-xr-x
146 146
147 147 Rebase the working copy parent
148 148 $ hg up -C 3
149 149 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 150 $ hg rebase -r 3 -d 0 --debug | grep rebasing
151 151 rebasing in memory
152 152 rebasing 3:753feb6fd12a tip "c"
153 153 $ hg tglog
154 154 @ 3: 844a7de3e617 'c'
155 155 |
156 156 | o 2: 09c044d2cb43 'd'
157 157 | |
158 158 | o 1: fc055c3b4d33 'b'
159 159 |/
160 160 o 0: b173517d0057 'a'
161 161
162 162
163 163 Test reporting of path conflicts
164 164
165 165 $ hg rm a
166 166 $ mkdir a
167 167 $ touch a/a
168 168 $ hg ci -Am "a/a"
169 169 adding a/a
170 170 $ hg tglog
171 171 @ 4: daf7dfc139cb 'a/a'
172 172 |
173 173 o 3: 844a7de3e617 'c'
174 174 |
175 175 | o 2: 09c044d2cb43 'd'
176 176 | |
177 177 | o 1: fc055c3b4d33 'b'
178 178 |/
179 179 o 0: b173517d0057 'a'
180 180
181 181 $ hg rebase -r . -d 2
182 182 rebasing 4:daf7dfc139cb tip "a/a"
183 183 saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/daf7dfc139cb-fdbfcf4f-rebase.hg
184 184
185 185 $ hg tglog
186 186 @ 4: c6ad37a4f250 'a/a'
187 187 |
188 188 | o 3: 844a7de3e617 'c'
189 189 | |
190 190 o | 2: 09c044d2cb43 'd'
191 191 | |
192 192 o | 1: fc055c3b4d33 'b'
193 193 |/
194 194 o 0: b173517d0057 'a'
195 195
196 196 $ echo foo > foo
197 197 $ hg ci -Aqm "added foo"
198 198 $ hg up '.^'
199 199 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
200 200 $ echo bar > bar
201 201 $ hg ci -Aqm "added bar"
202 202 $ hg rm a/a
203 203 $ echo a > a
204 204 $ hg ci -Aqm "added a back!"
205 205 $ hg tglog
206 206 @ 7: 855e9797387e 'added a back!'
207 207 |
208 208 o 6: d14530e5e3e6 'added bar'
209 209 |
210 210 | o 5: 9b94b9373deb 'added foo'
211 211 |/
212 212 o 4: c6ad37a4f250 'a/a'
213 213 |
214 214 | o 3: 844a7de3e617 'c'
215 215 | |
216 216 o | 2: 09c044d2cb43 'd'
217 217 | |
218 218 o | 1: fc055c3b4d33 'b'
219 219 |/
220 220 o 0: b173517d0057 'a'
221 221
222 222 $ hg rebase -r . -d 5
223 223 rebasing 7:855e9797387e tip "added a back!"
224 224 saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/855e9797387e-81ee4c5d-rebase.hg
225 225
226 226 $ hg tglog
227 227 @ 7: bb3f02be2688 'added a back!'
228 228 |
229 229 | o 6: d14530e5e3e6 'added bar'
230 230 | |
231 231 o | 5: 9b94b9373deb 'added foo'
232 232 |/
233 233 o 4: c6ad37a4f250 'a/a'
234 234 |
235 235 | o 3: 844a7de3e617 'c'
236 236 | |
237 237 o | 2: 09c044d2cb43 'd'
238 238 | |
239 239 o | 1: fc055c3b4d33 'b'
240 240 |/
241 241 o 0: b173517d0057 'a'
242 242
243 243 $ mkdir -p c/subdir
244 244 $ echo c > c/subdir/file.txt
245 245 $ hg add c/subdir/file.txt
246 246 $ hg ci -m 'c/subdir/file.txt'
247 247 $ hg rebase -r . -d 3 -n
248 248 starting dry-run rebase; repository will not be changed
249 249 rebasing 8:e147e6e3c490 tip "c/subdir/file.txt"
250 250 abort: error: 'c/subdir/file.txt' conflicts with file 'c' in 3.
251 251 [255]
252 252 FIXME: shouldn't need this, but when we hit path conflicts in dryrun mode, we
253 253 don't clean up rebasestate.
254 254 $ hg rebase --abort
255 255 rebase aborted
256 256 $ hg rebase -r 3 -d . -n
257 257 starting dry-run rebase; repository will not be changed
258 258 rebasing 3:844a7de3e617 "c"
259 259 abort: error: file 'c' cannot be written because 'c/' is a directory in e147e6e3c490 (containing 1 entries: c/subdir/file.txt)
260 260 [255]
261 261
262 262 $ cd ..
263 263
264 264 Test path auditing (issue5818)
265 265
266 266 $ mkdir lib_
267 267 $ ln -s lib_ lib
268 268 $ hg init repo
269 269 $ cd repo
270 270 $ mkdir -p ".$TESTTMP/lib"
271 271 $ touch ".$TESTTMP/lib/a"
272 272 $ hg add ".$TESTTMP/lib/a"
273 273 $ hg ci -m 'a'
274 274
275 275 $ touch ".$TESTTMP/lib/b"
276 276 $ hg add ".$TESTTMP/lib/b"
277 277 $ hg ci -m 'b'
278 278
279 279 $ hg up -q '.^'
280 280 $ touch ".$TESTTMP/lib/c"
281 281 $ hg add ".$TESTTMP/lib/c"
282 282 $ hg ci -m 'c'
283 283 created new head
284 284 $ hg rebase -s 1 -d .
285 285 rebasing 1:* "b" (glob)
286 286 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-rebase.hg (glob)
287 287 $ cd ..
288 288
289 289 Test dry-run rebasing
290 290
291 291 $ hg init repo3
292 292 $ cd repo3
293 293 $ echo a>a
294 294 $ hg ci -Aqma
295 295 $ echo b>b
296 296 $ hg ci -Aqmb
297 297 $ echo c>c
298 298 $ hg ci -Aqmc
299 299 $ echo d>d
300 300 $ hg ci -Aqmd
301 301 $ echo e>e
302 302 $ hg ci -Aqme
303 303
304 304 $ hg up 1 -q
305 305 $ echo f>f
306 306 $ hg ci -Amf
307 307 adding f
308 308 created new head
309 309 $ echo g>g
310 310 $ hg ci -Aqmg
311 311 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
312 312 @ 6:baf10c5166d4 test
313 313 | g
314 314 |
315 315 o 5:6343ca3eff20 test
316 316 | f
317 317 |
318 318 | o 4:e860deea161a test
319 319 | | e
320 320 | |
321 321 | o 3:055a42cdd887 test
322 322 | | d
323 323 | |
324 324 | o 2:177f92b77385 test
325 325 |/ c
326 326 |
327 327 o 1:d2ae7f538514 test
328 328 | b
329 329 |
330 330 o 0:cb9a9f314b8b test
331 331 a
332 332
333 333 Make sure it throws error while passing --continue or --abort with --dry-run
334 334 $ hg rebase -s 2 -d 6 -n --continue
335 335 abort: cannot specify both --continue and --dry-run
336 336 [10]
337 337 $ hg rebase -s 2 -d 6 -n --abort
338 338 abort: cannot specify both --abort and --dry-run
339 339 [10]
340 340
341 341 When nothing to rebase
342 342 $ hg reb -r . -d '.^' -n
343 343 starting dry-run rebase; repository will not be changed
344 344 nothing to rebase
345 345 [1]
346 346
347 347 Check dryrun gives correct results when there is no conflict in rebasing
348 348 $ hg rebase -s 2 -d 6 -n
349 349 starting dry-run rebase; repository will not be changed
350 350 rebasing 2:177f92b77385 "c"
351 351 rebasing 3:055a42cdd887 "d"
352 352 rebasing 4:e860deea161a "e"
353 353 dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase
354 354
355 355 $ hg diff
356 356 $ hg status
357 357
358 358 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
359 359 @ 6:baf10c5166d4 test
360 360 | g
361 361 |
362 362 o 5:6343ca3eff20 test
363 363 | f
364 364 |
365 365 | o 4:e860deea161a test
366 366 | | e
367 367 | |
368 368 | o 3:055a42cdd887 test
369 369 | | d
370 370 | |
371 371 | o 2:177f92b77385 test
372 372 |/ c
373 373 |
374 374 o 1:d2ae7f538514 test
375 375 | b
376 376 |
377 377 o 0:cb9a9f314b8b test
378 378 a
379 379
380 380 Check dryrun working with --collapse when there is no conflict
381 381 $ hg rebase -s 2 -d 6 -n --collapse
382 382 starting dry-run rebase; repository will not be changed
383 383 rebasing 2:177f92b77385 "c"
384 384 rebasing 3:055a42cdd887 "d"
385 385 rebasing 4:e860deea161a "e"
386 386 dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase
387 387
388 388 Check dryrun gives correct results when there is conflict in rebasing
389 389 Make a conflict:
390 390 $ hg up 6 -q
391 391 $ echo conflict>e
392 392 $ hg ci -Aqm "conflict with e"
393 393 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
394 394 @ 7:d2c195b28050 test
395 395 | conflict with e
396 396 |
397 397 o 6:baf10c5166d4 test
398 398 | g
399 399 |
400 400 o 5:6343ca3eff20 test
401 401 | f
402 402 |
403 403 | o 4:e860deea161a test
404 404 | | e
405 405 | |
406 406 | o 3:055a42cdd887 test
407 407 | | d
408 408 | |
409 409 | o 2:177f92b77385 test
410 410 |/ c
411 411 |
412 412 o 1:d2ae7f538514 test
413 413 | b
414 414 |
415 415 o 0:cb9a9f314b8b test
416 416 a
417 417
418 418 $ hg rebase -s 2 -d 7 -n
419 419 starting dry-run rebase; repository will not be changed
420 420 rebasing 2:177f92b77385 "c"
421 421 rebasing 3:055a42cdd887 "d"
422 422 rebasing 4:e860deea161a "e"
423 423 merging e
424 424 hit a merge conflict
425 425 [1]
426 426 $ hg diff
427 427 $ hg status
428 428 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
429 429 @ 7:d2c195b28050 test
430 430 | conflict with e
431 431 |
432 432 o 6:baf10c5166d4 test
433 433 | g
434 434 |
435 435 o 5:6343ca3eff20 test
436 436 | f
437 437 |
438 438 | o 4:e860deea161a test
439 439 | | e
440 440 | |
441 441 | o 3:055a42cdd887 test
442 442 | | d
443 443 | |
444 444 | o 2:177f92b77385 test
445 445 |/ c
446 446 |
447 447 o 1:d2ae7f538514 test
448 448 | b
449 449 |
450 450 o 0:cb9a9f314b8b test
451 451 a
452 452
453 453 Check dryrun working with --collapse when there is conflicts
454 454 $ hg rebase -s 2 -d 7 -n --collapse
455 455 starting dry-run rebase; repository will not be changed
456 456 rebasing 2:177f92b77385 "c"
457 457 rebasing 3:055a42cdd887 "d"
458 458 rebasing 4:e860deea161a "e"
459 459 merging e
460 460 hit a merge conflict
461 461 [1]
462 462
463 463 In-memory rebase that fails due to merge conflicts
464 464
465 465 $ hg rebase -s 2 -d 7
466 466 rebasing 2:177f92b77385 "c"
467 467 rebasing 3:055a42cdd887 "d"
468 468 rebasing 4:e860deea161a "e"
469 469 merging e
470 470 hit merge conflicts; rebasing that commit again in the working copy
471 471 merging e
472 472 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
473 473 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
474 474 [240]
475 475 $ hg rebase --abort
476 476 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/c1e524d4287c-f91f82e1-backup.hg
477 477 rebase aborted
478 478
479 479 Retrying without in-memory merge won't lose working copy changes
480 480 $ cd ..
481 481 $ hg clone repo3 repo3-dirty -q
482 482 $ cd repo3-dirty
483 483 $ echo dirty > a
484 484 $ hg rebase -s 2 -d 7
485 485 rebasing 2:177f92b77385 "c"
486 486 rebasing 3:055a42cdd887 "d"
487 487 rebasing 4:e860deea161a "e"
488 488 merging e
489 489 hit merge conflicts; rebasing that commit again in the working copy
490 490 transaction abort!
491 491 rollback completed
492 492 abort: uncommitted changes
493 493 [20]
494 494 $ cat a
495 495 dirty
496 496 $ hg status -v
497 497 M a
498 498
499 499 Retrying without in-memory merge won't lose merge state
500 500 $ cd ..
501 501 $ hg clone repo3 repo3-merge-state -q
502 502 $ cd repo3-merge-state
503 503 $ hg merge 4
504 504 merging e
505 505 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
506 506 2 files updated, 0 files merged, 0 files removed, 1 files unresolved
507 507 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
508 508 [1]
509 509 $ hg resolve -l
510 510 U e
511 511 $ hg rebase -s 2 -d 7
512 512 abort: outstanding uncommitted merge
513 513 (use 'hg commit' or 'hg merge --abort')
514 514 [20]
515 515 $ hg resolve -l
516 516 U e
517 517
518 518 ==========================
519 519 Test for --confirm option|
520 520 ==========================
521 521 $ cd ..
522 522 $ hg clone repo3 repo4 -q
523 523 $ cd repo4
524 524 $ hg strip 7 -q
525 525 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
526 526 @ 6:baf10c5166d4 test
527 527 | g
528 528 |
529 529 o 5:6343ca3eff20 test
530 530 | f
531 531 |
532 532 | o 4:e860deea161a test
533 533 | | e
534 534 | |
535 535 | o 3:055a42cdd887 test
536 536 | | d
537 537 | |
538 538 | o 2:177f92b77385 test
539 539 |/ c
540 540 |
541 541 o 1:d2ae7f538514 test
542 542 | b
543 543 |
544 544 o 0:cb9a9f314b8b test
545 545 a
546 546
547 547 Check it gives error when both --dryrun and --confirm is used:
548 548 $ hg rebase -s 2 -d . --confirm --dry-run
549 549 abort: cannot specify both --confirm and --dry-run
550 550 [10]
551 551 $ hg rebase -s 2 -d . --confirm --abort
552 552 abort: cannot specify both --abort and --confirm
553 553 [10]
554 554 $ hg rebase -s 2 -d . --confirm --continue
555 555 abort: cannot specify both --continue and --confirm
556 556 [10]
557 557
558 558 Test --confirm option when there are no conflicts:
559 559 $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
560 560 > n
561 561 > EOF
562 562 starting in-memory rebase
563 563 rebasing 2:177f92b77385 "c"
564 564 rebasing 3:055a42cdd887 "d"
565 565 rebasing 4:e860deea161a "e"
566 566 rebase completed successfully
567 567 apply changes (yn)? n
568 568 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
569 569 @ 6:baf10c5166d4 test
570 570 | g
571 571 |
572 572 o 5:6343ca3eff20 test
573 573 | f
574 574 |
575 575 | o 4:e860deea161a test
576 576 | | e
577 577 | |
578 578 | o 3:055a42cdd887 test
579 579 | | d
580 580 | |
581 581 | o 2:177f92b77385 test
582 582 |/ c
583 583 |
584 584 o 1:d2ae7f538514 test
585 585 | b
586 586 |
587 587 o 0:cb9a9f314b8b test
588 588 a
589 589
590 590 $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
591 591 > y
592 592 > EOF
593 593 starting in-memory rebase
594 594 rebasing 2:177f92b77385 "c"
595 595 rebasing 3:055a42cdd887 "d"
596 596 rebasing 4:e860deea161a "e"
597 597 rebase completed successfully
598 598 apply changes (yn)? y
599 599 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
600 600 o 9:9fd28f55f6dc test
601 601 | e
602 602 |
603 603 o 8:12cbf031f469 test
604 604 | d
605 605 |
606 606 o 7:c83b1da5b1ae test
607 607 | c
608 608 |
609 609 @ 6:baf10c5166d4 test
610 610 | g
611 611 |
612 612 o 5:6343ca3eff20 test
613 613 | f
614 614 |
615 615 | o 4:e860deea161a test
616 616 | | e
617 617 | |
618 618 | o 3:055a42cdd887 test
619 619 | | d
620 620 | |
621 621 | o 2:177f92b77385 test
622 622 |/ c
623 623 |
624 624 o 1:d2ae7f538514 test
625 625 | b
626 626 |
627 627 o 0:cb9a9f314b8b test
628 628 a
629 629
630 630 Test --confirm option when there is a conflict
631 631 $ hg up tip -q
632 632 $ echo ee>e
633 633 $ hg ci --amend -m "conflict with e" -q
634 634 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
635 635 @ 9:906d72f66a59 test
636 636 | conflict with e
637 637 |
638 638 o 8:12cbf031f469 test
639 639 | d
640 640 |
641 641 o 7:c83b1da5b1ae test
642 642 | c
643 643 |
644 644 o 6:baf10c5166d4 test
645 645 | g
646 646 |
647 647 o 5:6343ca3eff20 test
648 648 | f
649 649 |
650 650 | o 4:e860deea161a test
651 651 | | e
652 652 | |
653 653 | o 3:055a42cdd887 test
654 654 | | d
655 655 | |
656 656 | o 2:177f92b77385 test
657 657 |/ c
658 658 |
659 659 o 1:d2ae7f538514 test
660 660 | b
661 661 |
662 662 o 0:cb9a9f314b8b test
663 663 a
664 664
665 665 $ hg rebase -s 4 -d . --keep --confirm
666 666 starting in-memory rebase
667 667 rebasing 4:e860deea161a "e"
668 668 merging e
669 669 hit a merge conflict
670 670 [1]
671 671 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
672 672 @ 9:906d72f66a59 test
673 673 | conflict with e
674 674 |
675 675 o 8:12cbf031f469 test
676 676 | d
677 677 |
678 678 o 7:c83b1da5b1ae test
679 679 | c
680 680 |
681 681 o 6:baf10c5166d4 test
682 682 | g
683 683 |
684 684 o 5:6343ca3eff20 test
685 685 | f
686 686 |
687 687 | o 4:e860deea161a test
688 688 | | e
689 689 | |
690 690 | o 3:055a42cdd887 test
691 691 | | d
692 692 | |
693 693 | o 2:177f92b77385 test
694 694 |/ c
695 695 |
696 696 o 1:d2ae7f538514 test
697 697 | b
698 698 |
699 699 o 0:cb9a9f314b8b test
700 700 a
701 701
702 702 Test a metadata-only in-memory merge
703 703 $ cd $TESTTMP
704 704 $ hg init no_exception
705 705 $ cd no_exception
706 706 # Produce the following graph:
707 707 # o 'add +x to foo.txt'
708 708 # | o r1 (adds bar.txt, just for something to rebase to)
709 709 # |/
710 710 # o r0 (adds foo.txt, no +x)
711 711 $ echo hi > foo.txt
712 712 $ hg ci -qAm r0
713 713 $ echo hi > bar.txt
714 714 $ hg ci -qAm r1
715 715 $ hg co -qr ".^"
716 716 $ chmod +x foo.txt
717 717 $ hg ci -qAm 'add +x to foo.txt'
718 718 issue5960: this was raising an AttributeError exception
719 719 $ hg rebase -r . -d 1
720 720 rebasing 2:539b93e77479 tip "add +x to foo.txt"
721 721 saved backup bundle to $TESTTMP/no_exception/.hg/strip-backup/*.hg (glob)
722 722 $ hg diff -c tip
723 723 diff --git a/foo.txt b/foo.txt
724 724 old mode 100644
725 725 new mode 100755
726 726
727 727 Test rebasing a commit with copy information, but no content changes
728 728
729 729 $ cd ..
730 730 $ hg clone -q repo1 merge-and-rename
731 731 $ cd merge-and-rename
732 732 $ cat << EOF >> .hg/hgrc
733 733 > [experimental]
734 734 > evolution.createmarkers=True
735 735 > evolution.allowunstable=True
736 736 > EOF
737 737 $ hg co -q 1
738 738 $ hg mv d e
739 739 $ hg ci -qm 'rename d to e'
740 740 $ hg co -q 3
741 741 $ hg merge -q 4
742 742 $ hg ci -m 'merge'
743 743 $ hg co -q 2
744 744 $ mv d e
745 745 $ hg addremove -qs 0
746 746 $ hg ci -qm 'untracked rename of d to e'
747 747 $ hg debugobsolete -q `hg log -T '{node}' -r 4` `hg log -T '{node}' -r .`
748 748 1 new orphan changesets
749 749 $ hg tglog
750 750 @ 6: 676538af172d 'untracked rename of d to e'
751 751 |
752 752 | * 5: 574d92ad16fc 'merge'
753 753 | |\
754 754 | | x 4: 2c8b5dad7956 'rename d to e'
755 755 | | |
756 756 | o | 3: ca58782ad1e4 'b'
757 757 |/ /
758 758 o / 2: 814f6bd05178 'c'
759 759 |/
760 760 o 1: 02952614a83d 'd'
761 761 |
762 762 o 0: b173517d0057 'a'
763 763
764 764 $ hg rebase -b 5 -d tip
765 765 rebasing 3:ca58782ad1e4 "b"
766 766 rebasing 5:574d92ad16fc "merge"
767 767 note: not rebasing 5:574d92ad16fc "merge", its destination already has all its changes
768 768
769 769 $ cd ..
770 770
771 771 Test rebasing a commit with copy information
772 772
773 773 $ hg init rebase-rename
774 774 $ cd rebase-rename
775 775 $ echo a > a
776 776 $ hg ci -Aqm 'add a'
777 777 $ echo a2 > a
778 778 $ hg ci -m 'modify a'
779 779 $ hg co -q 0
780 780 $ hg mv a b
781 781 $ hg ci -qm 'rename a to b'
782 782 $ hg rebase -d 1
783 783 rebasing 2:b977edf6f839 tip "rename a to b"
784 784 merging a and b to b
785 785 saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg
786 786 $ hg st --copies --change .
787 787 A b
788 788 a
789 789 R a
790 790 $ cd ..
791 791
792 792 Test rebasing a commit with copy information, where the target is empty
793 793
794 794 $ hg init rebase-rename-empty
795 795 $ cd rebase-rename-empty
796 796 $ echo a > a
797 797 $ hg ci -Aqm 'add a'
798 798 $ cat > a
799 799 $ hg ci -m 'make a empty'
800 800 $ hg co -q 0
801 801 $ hg mv a b
802 802 $ hg ci -qm 'rename a to b'
803 803 $ hg rebase -d 1
804 804 rebasing 2:b977edf6f839 tip "rename a to b"
805 805 merging a and b to b
806 806 saved backup bundle to $TESTTMP/rebase-rename-empty/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg
807 807 $ hg st --copies --change .
808 808 A b
809 809 a
810 810 R a
811 811 $ cd ..
812 812 Rebase across a copy with --collapse
813 813
814 814 $ hg init rebase-rename-collapse
815 815 $ cd rebase-rename-collapse
816 816 $ echo a > a
817 817 $ hg ci -Aqm 'add a'
818 818 $ hg mv a b
819 819 $ hg ci -m 'rename a to b'
820 820 $ hg co -q 0
821 821 $ echo a2 > a
822 822 $ hg ci -qm 'modify a'
823 823 $ hg rebase -r . -d 1 --collapse
824 824 rebasing 2:41c4ea50d4cf tip "modify a"
825 825 merging b and a to b
826 826 saved backup bundle to $TESTTMP/rebase-rename-collapse/.hg/strip-backup/41c4ea50d4cf-b90b7994-rebase.hg
827 827 $ cd ..
828 828
829 829 Test rebasing when the file we are merging in destination is empty
830 830
831 831 $ hg init test
832 832 $ cd test
833 833 $ echo a > foo
834 834 $ hg ci -Aqm 'added a to foo'
835 835
836 836 $ rm foo
837 837 $ touch foo
838 838 $ hg di
839 839 diff --git a/foo b/foo
840 840 --- a/foo
841 841 +++ b/foo
842 842 @@ -1,1 +0,0 @@
843 843 -a
844 844
845 845 $ hg ci -m "make foo an empty file"
846 846
847 847 $ hg up '.^'
848 848 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
849 849 $ echo b > foo
850 850 $ hg di
851 851 diff --git a/foo b/foo
852 852 --- a/foo
853 853 +++ b/foo
854 854 @@ -1,1 +1,1 @@
855 855 -a
856 856 +b
857 857 $ hg ci -m "add b to foo"
858 858 created new head
859 859
860 860 $ hg rebase -r . -d 1 --config ui.merge=internal:merge3
861 861 rebasing 2:fb62b706688e tip "add b to foo"
862 862 merging foo
863 863 hit merge conflicts; rebasing that commit again in the working copy
864 864 merging foo
865 865 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
866 866 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
867 867 [240]
868 868
869 869 $ cd $TESTTMP
870 870
871 871 Test rebasing when we're in the middle of a rebase already
872 872 $ hg init test_issue6214
873 873 $ cd test_issue6214
874 874 $ echo r0 > r0
875 875 $ hg ci -qAm 'r0'
876 876 $ echo hi > foo
877 877 $ hg ci -qAm 'hi from foo'
878 878 $ hg co -q '.^'
879 879 $ echo bye > foo
880 880 $ hg ci -qAm 'bye from foo'
881 881 $ hg co -q '.^'
882 882 $ echo unrelated > some_other_file
883 883 $ hg ci -qAm 'some unrelated changes'
884 884 $ hg log -G -T'{rev}: {desc}\n{files%"{file}\n"}'
885 885 @ 3: some unrelated changes
886 886 | some_other_file
887 887 | o 2: bye from foo
888 888 |/ foo
889 889 | o 1: hi from foo
890 890 |/ foo
891 891 o 0: r0
892 892 r0
893 893 $ hg rebase -r 2 -d 1 -t:merge3
894 894 rebasing 2:b4d249fbf8dd "bye from foo"
895 895 merging foo
896 896 hit merge conflicts; rebasing that commit again in the working copy
897 897 merging foo
898 898 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
899 899 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
900 900 [240]
901 901 $ hg rebase -r 3 -d 1 -t:merge3
902 902 abort: rebase in progress
903 903 (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop')
904 904 [20]
905 905 $ hg resolve --list
906 906 U foo
907 907 $ hg resolve --all --re-merge -t:other
908 908 (no more unresolved files)
909 909 continue: hg rebase --continue
910 910 $ hg rebase --continue
911 911 rebasing 2:b4d249fbf8dd "bye from foo"
912 912 saved backup bundle to $TESTTMP/test_issue6214/.hg/strip-backup/b4d249fbf8dd-299ec25c-rebase.hg
913 913 $ hg log -G -T'{rev}: {desc}\n{files%"{file}\n"}'
914 914 o 3: bye from foo
915 915 | foo
916 916 | @ 2: some unrelated changes
917 917 | | some_other_file
918 918 o | 1: hi from foo
919 919 |/ foo
920 920 o 0: r0
921 921 r0
922 922
923 923 $ cd ..
924 924
925 925 Changesets that become empty should not be committed. Merges are not empty by
926 926 definition.
927 927
928 928 $ hg init keep_merge
929 929 $ cd keep_merge
930 930 $ echo base > base; hg add base; hg ci -m base
931 931 $ echo test > test; hg add test; hg ci -m a
932 932 $ hg up 0 -q
933 933 $ echo test > test; hg add test; hg ci -m b -q
934 934 $ hg up 0 -q
935 935 $ echo test > test; hg add test; hg ci -m c -q
936 936 $ hg up 1 -q
937 937 $ hg merge 2 -q
938 938 $ hg ci -m merge
939 939 $ hg up null -q
940 940 $ hg tglog
941 941 o 4: 59c8292117b1 'merge'
942 942 |\
943 943 | | o 3: 531f80391e4a 'c'
944 944 | | |
945 945 | o | 2: 0194f1db184a 'b'
946 946 | |/
947 947 o / 1: 6f252845ea45 'a'
948 948 |/
949 949 o 0: d20a80d4def3 'base'
950 950
951 951 $ hg rebase -s 2 -d 3
952 952 rebasing 2:0194f1db184a "b"
953 953 note: not rebasing 2:0194f1db184a "b", its destination already has all its changes
954 954 rebasing 4:59c8292117b1 tip "merge"
955 955 saved backup bundle to $TESTTMP/keep_merge/.hg/strip-backup/0194f1db184a-aee31d03-rebase.hg
956 956 $ hg tglog
957 957 o 3: 506e2454484b 'merge'
958 958 |\
959 959 | o 2: 531f80391e4a 'c'
960 960 | |
961 961 o | 1: 6f252845ea45 'a'
962 962 |/
963 963 o 0: d20a80d4def3 'base'
964 964
965 965
966 966 Test that update_hash_refs works.
967 967 $ hg co 0
968 968 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
969 969 $ echo update_hash_refs > update_hash_refs
970 970 $ hg add update_hash_refs
971 971 $ hg ci -m 'this will change hash'
972 972 created new head
973 973 $ echo changed >> update_hash_refs
974 $ hg ci -m "this starts as the child of `hg log -r . -T'{node|short}'` but not 506e2454484b"
974 $ hg ci -m "this starts as the child of `hg log -r . -T'{node|short}'` but not 506e2454484b. Also, ffffffffffffffff"
975 975 $ hg tglog
976 @ 5: becd28036887 'this starts as the child of 98789aa60148 but not 506e2454484b'
976 @ 5: a8b42cbbde83 'this starts as the child of 98789aa60148 but not 506e2454484b. Also, ffffffffffffffff'
977 977 |
978 978 o 4: 98789aa60148 'this will change hash'
979 979 |
980 980 | o 3: 506e2454484b 'merge'
981 981 | |\
982 982 +---o 2: 531f80391e4a 'c'
983 983 | |
984 984 | o 1: 6f252845ea45 'a'
985 985 |/
986 986 o 0: d20a80d4def3 'base'
987 987
988 988 $ hg rebase -r '.^::' -d 3
989 989 rebasing 4:98789aa60148 "this will change hash"
990 rebasing 5:becd28036887 tip "this starts as the child of 98789aa60148 but not 506e2454484b"
991 saved backup bundle to $TESTTMP/keep_merge/.hg/strip-backup/98789aa60148-72ec40bd-rebase.hg
990 rebasing 5:a8b42cbbde83 tip "this starts as the child of 98789aa60148 but not 506e2454484b. Also, ffffffffffffffff"
991 saved backup bundle to $TESTTMP/keep_merge/.hg/strip-backup/98789aa60148-da3f4c2c-rebase.hg
992 992 $ hg tglog
993 @ 5: a445b8426f4b 'this starts as the child of c16c25696fe7 but not 506e2454484b'
993 @ 5: 0fd2912e6cc1 'this starts as the child of c16c25696fe7 but not 506e2454484b. Also, ffffffffffffffff'
994 994 |
995 995 o 4: c16c25696fe7 'this will change hash'
996 996 |
997 997 o 3: 506e2454484b 'merge'
998 998 |\
999 999 | o 2: 531f80391e4a 'c'
1000 1000 | |
1001 1001 o | 1: 6f252845ea45 'a'
1002 1002 |/
1003 1003 o 0: d20a80d4def3 'base'
1004 1004
1005 1005
1006 1006 $ cd ..
1007 1007
1008 1008 Test (virtual) working directory without changes, created by merge conflict
1009 1009 resolution. There was a regression where the file was incorrectly detected as
1010 1010 changed although the file contents were the same as in the parent.
1011 1011
1012 1012 $ hg init nofilechanges
1013 1013 $ cd nofilechanges
1014 1014 $ echo a > a; hg add a; hg ci -m a
1015 1015 $ echo foo > test; hg add test; hg ci -m b
1016 1016 $ hg up 0 -q
1017 1017 $ echo bar > test; hg add test; hg ci -m c
1018 1018 created new head
1019 1019 $ hg rebase -d 2 -d 1 --tool :local
1020 1020 rebasing 2:ca2749322ee5 tip "c"
1021 1021 note: not rebasing 2:ca2749322ee5 tip "c", its destination already has all its changes
1022 1022 saved backup bundle to $TESTTMP/nofilechanges/.hg/strip-backup/ca2749322ee5-6dc7e94b-rebase.hg
General Comments 0
You need to be logged in to leave comments. Login now