##// END OF EJS Templates
histedit: record histedit source (issue3681)...
Pierre-Yves David -
r18437:358c23e8 default
parent child Browse files
Show More
@@ -1,790 +1,799 b''
1 1 # histedit.py - interactive history editing for mercurial
2 2 #
3 3 # Copyright 2009 Augie Fackler <raf@durin42.com>
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 """interactive history editing
8 8
9 9 With this extension installed, Mercurial gains one new command: histedit. Usage
10 10 is as follows, assuming the following history::
11 11
12 12 @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42
13 13 | Add delta
14 14 |
15 15 o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42
16 16 | Add gamma
17 17 |
18 18 o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42
19 19 | Add beta
20 20 |
21 21 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
22 22 Add alpha
23 23
24 24 If you were to run ``hg histedit c561b4e977df``, you would see the following
25 25 file open in your editor::
26 26
27 27 pick c561b4e977df Add beta
28 28 pick 030b686bedc4 Add gamma
29 29 pick 7c2fd3b9020c Add delta
30 30
31 31 # Edit history between c561b4e977df and 7c2fd3b9020c
32 32 #
33 33 # Commands:
34 34 # p, pick = use commit
35 35 # e, edit = use commit, but stop for amending
36 36 # f, fold = use commit, but fold into previous commit (combines N and N-1)
37 37 # d, drop = remove commit from history
38 38 # m, mess = edit message without changing commit content
39 39 #
40 40
41 41 In this file, lines beginning with ``#`` are ignored. You must specify a rule
42 42 for each revision in your history. For example, if you had meant to add gamma
43 43 before beta, and then wanted to add delta in the same revision as beta, you
44 44 would reorganize the file to look like this::
45 45
46 46 pick 030b686bedc4 Add gamma
47 47 pick c561b4e977df Add beta
48 48 fold 7c2fd3b9020c Add delta
49 49
50 50 # Edit history between c561b4e977df and 7c2fd3b9020c
51 51 #
52 52 # Commands:
53 53 # p, pick = use commit
54 54 # e, edit = use commit, but stop for amending
55 55 # f, fold = use commit, but fold into previous commit (combines N and N-1)
56 56 # d, drop = remove commit from history
57 57 # m, mess = edit message without changing commit content
58 58 #
59 59
60 60 At which point you close the editor and ``histedit`` starts working. When you
61 61 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
62 62 those revisions together, offering you a chance to clean up the commit message::
63 63
64 64 Add beta
65 65 ***
66 66 Add delta
67 67
68 68 Edit the commit message to your liking, then close the editor. For
69 69 this example, let's assume that the commit message was changed to
70 70 ``Add beta and delta.`` After histedit has run and had a chance to
71 71 remove any old or temporary revisions it needed, the history looks
72 72 like this::
73 73
74 74 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
75 75 | Add beta and delta.
76 76 |
77 77 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
78 78 | Add gamma
79 79 |
80 80 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
81 81 Add alpha
82 82
83 83 Note that ``histedit`` does *not* remove any revisions (even its own temporary
84 84 ones) until after it has completed all the editing operations, so it will
85 85 probably perform several strip operations when it's done. For the above example,
86 86 it had to run strip twice. Strip can be slow depending on a variety of factors,
87 87 so you might need to be a little patient. You can choose to keep the original
88 88 revisions by passing the ``--keep`` flag.
89 89
90 90 The ``edit`` operation will drop you back to a command prompt,
91 91 allowing you to edit files freely, or even use ``hg record`` to commit
92 92 some changes as a separate commit. When you're done, any remaining
93 93 uncommitted changes will be committed as well. When done, run ``hg
94 94 histedit --continue`` to finish this step. You'll be prompted for a
95 95 new commit message, but the default commit message will be the
96 96 original message for the ``edit`` ed revision.
97 97
98 98 The ``message`` operation will give you a chance to revise a commit
99 99 message without changing the contents. It's a shortcut for doing
100 100 ``edit`` immediately followed by `hg histedit --continue``.
101 101
102 102 If ``histedit`` encounters a conflict when moving a revision (while
103 103 handling ``pick`` or ``fold``), it'll stop in a similar manner to
104 104 ``edit`` with the difference that it won't prompt you for a commit
105 105 message when done. If you decide at this point that you don't like how
106 106 much work it will be to rearrange history, or that you made a mistake,
107 107 you can use ``hg histedit --abort`` to abandon the new changes you
108 108 have made and return to the state before you attempted to edit your
109 109 history.
110 110
111 111 If we clone the histedit-ed example repository above and add four more
112 112 changes, such that we have the following history::
113 113
114 114 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
115 115 | Add theta
116 116 |
117 117 o 5 140988835471 2009-04-27 18:04 -0500 stefan
118 118 | Add eta
119 119 |
120 120 o 4 122930637314 2009-04-27 18:04 -0500 stefan
121 121 | Add zeta
122 122 |
123 123 o 3 836302820282 2009-04-27 18:04 -0500 stefan
124 124 | Add epsilon
125 125 |
126 126 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
127 127 | Add beta and delta.
128 128 |
129 129 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
130 130 | Add gamma
131 131 |
132 132 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
133 133 Add alpha
134 134
135 135 If you run ``hg histedit --outgoing`` on the clone then it is the same
136 136 as running ``hg histedit 836302820282``. If you need plan to push to a
137 137 repository that Mercurial does not detect to be related to the source
138 138 repo, you can add a ``--force`` option.
139 139 """
140 140
141 141 try:
142 142 import cPickle as pickle
143 143 except ImportError:
144 144 import pickle
145 145 import os
146 146
147 147 from mercurial import cmdutil
148 148 from mercurial import discovery
149 149 from mercurial import error
150 150 from mercurial import copies
151 151 from mercurial import context
152 152 from mercurial import hg
153 153 from mercurial import lock as lockmod
154 154 from mercurial import node
155 155 from mercurial import repair
156 156 from mercurial import scmutil
157 157 from mercurial import util
158 158 from mercurial import obsolete
159 159 from mercurial import merge as mergemod
160 160 from mercurial.i18n import _
161 161
162 162 cmdtable = {}
163 163 command = cmdutil.command(cmdtable)
164 164
165 165 testedwith = 'internal'
166 166
167 167 # i18n: command names and abbreviations must remain untranslated
168 168 editcomment = _("""# Edit history between %s and %s
169 169 #
170 170 # Commands:
171 171 # p, pick = use commit
172 172 # e, edit = use commit, but stop for amending
173 173 # f, fold = use commit, but fold into previous commit (combines N and N-1)
174 174 # d, drop = remove commit from history
175 175 # m, mess = edit message without changing commit content
176 176 #
177 177 """)
178 178
179 179 def commitfuncfor(repo, src):
180 180 """Build a commit function for the replacement of <src>
181 181
182 182 This function ensure we apply the same treatement to all changesets.
183 183
184 No such treatment is done yet.
184 - Add a 'histedit_source' entry in extra.
185 185
186 186 Note that fold have its own separated logic because its handling is a bit
187 187 different and not easily factored out of the fold method.
188 188 """
189 189 def commitfunc(**kwargs):
190 extra = kwargs.get('extra', {}).copy()
191 extra['histedit_source'] = src.hex()
192 kwargs['extra'] = extra
190 193 return repo.commit(**kwargs)
191 194 return commitfunc
192 195
193 196
194 197
195 198 def applychanges(ui, repo, ctx, opts):
196 199 """Merge changeset from ctx (only) in the current working directory"""
197 200 wcpar = repo.dirstate.parents()[0]
198 201 if ctx.p1().node() == wcpar:
199 202 # edition ar "in place" we do not need to make any merge,
200 203 # just applies changes on parent for edition
201 204 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
202 205 stats = None
203 206 else:
204 207 try:
205 208 # ui.forcemerge is an internal variable, do not document
206 209 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
207 210 stats = mergemod.update(repo, ctx.node(), True, True, False,
208 211 ctx.p1().node())
209 212 finally:
210 213 repo.ui.setconfig('ui', 'forcemerge', '')
211 214 repo.setparents(wcpar, node.nullid)
212 215 repo.dirstate.write()
213 216 # fix up dirstate for copies and renames
214 217 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
215 218 return stats
216 219
217 220 def collapse(repo, first, last, commitopts):
218 221 """collapse the set of revisions from first to last as new one.
219 222
220 223 Expected commit options are:
221 224 - message
222 225 - date
223 226 - username
224 227 Commit message is edited in all cases.
225 228
226 229 This function works in memory."""
227 230 ctxs = list(repo.set('%d::%d', first, last))
228 231 if not ctxs:
229 232 return None
230 233 base = first.parents()[0]
231 234
232 235 # commit a new version of the old changeset, including the update
233 236 # collect all files which might be affected
234 237 files = set()
235 238 for ctx in ctxs:
236 239 files.update(ctx.files())
237 240
238 241 # Recompute copies (avoid recording a -> b -> a)
239 242 copied = copies.pathcopies(first, last)
240 243
241 244 # prune files which were reverted by the updates
242 245 def samefile(f):
243 246 if f in last.manifest():
244 247 a = last.filectx(f)
245 248 if f in base.manifest():
246 249 b = base.filectx(f)
247 250 return (a.data() == b.data()
248 251 and a.flags() == b.flags())
249 252 else:
250 253 return False
251 254 else:
252 255 return f not in base.manifest()
253 256 files = [f for f in files if not samefile(f)]
254 257 # commit version of these files as defined by head
255 258 headmf = last.manifest()
256 259 def filectxfn(repo, ctx, path):
257 260 if path in headmf:
258 261 fctx = last[path]
259 262 flags = fctx.flags()
260 263 mctx = context.memfilectx(fctx.path(), fctx.data(),
261 264 islink='l' in flags,
262 265 isexec='x' in flags,
263 266 copied=copied.get(path))
264 267 return mctx
265 268 raise IOError()
266 269
267 270 if commitopts.get('message'):
268 271 message = commitopts['message']
269 272 else:
270 273 message = first.description()
271 274 user = commitopts.get('user')
272 275 date = commitopts.get('date')
273 extra = first.extra()
276 extra = commitopts.get('extra')
274 277
275 278 parents = (first.p1().node(), first.p2().node())
276 279 new = context.memctx(repo,
277 280 parents=parents,
278 281 text=message,
279 282 files=files,
280 283 filectxfn=filectxfn,
281 284 user=user,
282 285 date=date,
283 286 extra=extra)
284 287 new._text = cmdutil.commitforceeditor(repo, new, [])
285 288 return repo.commitctx(new)
286 289
287 290 def pick(ui, repo, ctx, ha, opts):
288 291 oldctx = repo[ha]
289 292 if oldctx.parents()[0] == ctx:
290 293 ui.debug('node %s unchanged\n' % ha)
291 294 return oldctx, []
292 295 hg.update(repo, ctx.node())
293 296 stats = applychanges(ui, repo, oldctx, opts)
294 297 if stats and stats[3] > 0:
295 298 raise util.Abort(_('Fix up the change and run '
296 299 'hg histedit --continue'))
297 300 # drop the second merge parent
298 301 commit = commitfuncfor(repo, oldctx)
299 302 n = commit(text=oldctx.description(), user=oldctx.user(),
300 303 date=oldctx.date(), extra=oldctx.extra())
301 304 if n is None:
302 305 ui.warn(_('%s: empty changeset\n')
303 306 % node.hex(ha))
304 307 return ctx, []
305 308 new = repo[n]
306 309 return new, [(oldctx.node(), (n,))]
307 310
308 311
309 312 def edit(ui, repo, ctx, ha, opts):
310 313 oldctx = repo[ha]
311 314 hg.update(repo, ctx.node())
312 315 applychanges(ui, repo, oldctx, opts)
313 316 raise util.Abort(_('Make changes as needed, you may commit or record as '
314 317 'needed now.\nWhen you are finished, run hg'
315 318 ' histedit --continue to resume.'))
316 319
317 320 def fold(ui, repo, ctx, ha, opts):
318 321 oldctx = repo[ha]
319 322 hg.update(repo, ctx.node())
320 323 stats = applychanges(ui, repo, oldctx, opts)
321 324 if stats and stats[3] > 0:
322 325 raise util.Abort(_('Fix up the change and run '
323 326 'hg histedit --continue'))
324 327 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
325 328 date=oldctx.date(), extra=oldctx.extra())
326 329 if n is None:
327 330 ui.warn(_('%s: empty changeset')
328 331 % node.hex(ha))
329 332 return ctx, []
330 333 return finishfold(ui, repo, ctx, oldctx, n, opts, [])
331 334
332 335 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
333 336 parent = ctx.parents()[0].node()
334 337 hg.update(repo, parent)
335 338 ### prepare new commit data
336 339 commitopts = opts.copy()
337 340 # username
338 341 if ctx.user() == oldctx.user():
339 342 username = ctx.user()
340 343 else:
341 344 username = ui.username()
342 345 commitopts['user'] = username
343 346 # commit message
344 347 newmessage = '\n***\n'.join(
345 348 [ctx.description()] +
346 349 [repo[r].description() for r in internalchanges] +
347 350 [oldctx.description()]) + '\n'
348 351 commitopts['message'] = newmessage
349 352 # date
350 353 commitopts['date'] = max(ctx.date(), oldctx.date())
354 extra = ctx.extra().copy()
355 # histedit_source
356 # note: ctx is likely a temporary commit but that the best we can do here
357 # This is sufficient to solve issue3681 anyway
358 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
359 commitopts['extra'] = extra
351 360 n = collapse(repo, ctx, repo[newnode], commitopts)
352 361 if n is None:
353 362 return ctx, []
354 363 hg.update(repo, n)
355 364 replacements = [(oldctx.node(), (newnode,)),
356 365 (ctx.node(), (n,)),
357 366 (newnode, (n,)),
358 367 ]
359 368 for ich in internalchanges:
360 369 replacements.append((ich, (n,)))
361 370 return repo[n], replacements
362 371
363 372 def drop(ui, repo, ctx, ha, opts):
364 373 return ctx, [(repo[ha].node(), ())]
365 374
366 375
367 376 def message(ui, repo, ctx, ha, opts):
368 377 oldctx = repo[ha]
369 378 hg.update(repo, ctx.node())
370 379 stats = applychanges(ui, repo, oldctx, opts)
371 380 if stats and stats[3] > 0:
372 381 raise util.Abort(_('Fix up the change and run '
373 382 'hg histedit --continue'))
374 383 message = oldctx.description() + '\n'
375 384 message = ui.edit(message, ui.username())
376 385 commit = commitfuncfor(repo, oldctx)
377 386 new = commit(text=message, user=oldctx.user(), date=oldctx.date(),
378 387 extra=oldctx.extra())
379 388 newctx = repo[new]
380 389 if oldctx.node() != newctx.node():
381 390 return newctx, [(oldctx.node(), (new,))]
382 391 # We didn't make an edit, so just indicate no replaced nodes
383 392 return newctx, []
384 393
385 394 actiontable = {'p': pick,
386 395 'pick': pick,
387 396 'e': edit,
388 397 'edit': edit,
389 398 'f': fold,
390 399 'fold': fold,
391 400 'd': drop,
392 401 'drop': drop,
393 402 'm': message,
394 403 'mess': message,
395 404 }
396 405
397 406 @command('histedit',
398 407 [('', 'commands', '',
399 408 _('Read history edits from the specified file.')),
400 409 ('c', 'continue', False, _('continue an edit already in progress')),
401 410 ('k', 'keep', False,
402 411 _("don't strip old nodes after edit is complete")),
403 412 ('', 'abort', False, _('abort an edit in progress')),
404 413 ('o', 'outgoing', False, _('changesets not found in destination')),
405 414 ('f', 'force', False,
406 415 _('force outgoing even for unrelated repositories')),
407 416 ('r', 'rev', [], _('first revision to be edited'))],
408 417 _("[PARENT]"))
409 418 def histedit(ui, repo, *parent, **opts):
410 419 """interactively edit changeset history
411 420 """
412 421 # TODO only abort if we try and histedit mq patches, not just
413 422 # blanket if mq patches are applied somewhere
414 423 mq = getattr(repo, 'mq', None)
415 424 if mq and mq.applied:
416 425 raise util.Abort(_('source has mq patches applied'))
417 426
418 427 parent = list(parent) + opts.get('rev', [])
419 428 if opts.get('outgoing'):
420 429 if len(parent) > 1:
421 430 raise util.Abort(
422 431 _('only one repo argument allowed with --outgoing'))
423 432 elif parent:
424 433 parent = parent[0]
425 434
426 435 dest = ui.expandpath(parent or 'default-push', parent or 'default')
427 436 dest, revs = hg.parseurl(dest, None)[:2]
428 437 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
429 438
430 439 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
431 440 other = hg.peer(repo, opts, dest)
432 441
433 442 if revs:
434 443 revs = [repo.lookup(rev) for rev in revs]
435 444
436 445 parent = discovery.findcommonoutgoing(
437 446 repo, other, [], force=opts.get('force')).missing[0:1]
438 447 else:
439 448 if opts.get('force'):
440 449 raise util.Abort(_('--force only allowed with --outgoing'))
441 450
442 451 if opts.get('continue', False):
443 452 if len(parent) != 0:
444 453 raise util.Abort(_('no arguments allowed with --continue'))
445 454 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
446 455 currentparent, wantnull = repo.dirstate.parents()
447 456 parentctx = repo[parentctxnode]
448 457 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
449 458 replacements.extend(repl)
450 459 elif opts.get('abort', False):
451 460 if len(parent) != 0:
452 461 raise util.Abort(_('no arguments allowed with --abort'))
453 462 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
454 463 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
455 464 ui.debug('restore wc to old parent %s\n' % node.short(topmost))
456 465 hg.clean(repo, topmost)
457 466 cleanupnode(ui, repo, 'created', tmpnodes)
458 467 cleanupnode(ui, repo, 'temp', leafs)
459 468 os.unlink(os.path.join(repo.path, 'histedit-state'))
460 469 return
461 470 else:
462 471 cmdutil.bailifchanged(repo)
463 472 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
464 473 raise util.Abort(_('history edit already in progress, try '
465 474 '--continue or --abort'))
466 475
467 476 topmost, empty = repo.dirstate.parents()
468 477
469 478 if len(parent) != 1:
470 479 raise util.Abort(_('histedit requires exactly one parent revision'))
471 480 parent = scmutil.revsingle(repo, parent[0]).node()
472 481
473 482 keep = opts.get('keep', False)
474 483 revs = between(repo, parent, topmost, keep)
475 484 if not revs:
476 485 ui.warn(_('nothing to edit\n'))
477 486 return 1
478 487
479 488 ctxs = [repo[r] for r in revs]
480 489 rules = opts.get('commands', '')
481 490 if not rules:
482 491 rules = '\n'.join([makedesc(c) for c in ctxs])
483 492 rules += '\n\n'
484 493 rules += editcomment % (node.short(parent), node.short(topmost))
485 494 rules = ui.edit(rules, ui.username())
486 495 # Save edit rules in .hg/histedit-last-edit.txt in case
487 496 # the user needs to ask for help after something
488 497 # surprising happens.
489 498 f = open(repo.join('histedit-last-edit.txt'), 'w')
490 499 f.write(rules)
491 500 f.close()
492 501 else:
493 502 f = open(rules)
494 503 rules = f.read()
495 504 f.close()
496 505 rules = [l for l in (r.strip() for r in rules.splitlines())
497 506 if l and not l[0] == '#']
498 507 rules = verifyrules(rules, repo, ctxs)
499 508
500 509 parentctx = repo[parent].parents()[0]
501 510 keep = opts.get('keep', False)
502 511 replacements = []
503 512
504 513
505 514 while rules:
506 515 writestate(repo, parentctx.node(), rules, keep, topmost, replacements)
507 516 action, ha = rules.pop(0)
508 517 ui.debug('histedit: processing %s %s\n' % (action, ha))
509 518 actfunc = actiontable[action]
510 519 parentctx, replacement_ = actfunc(ui, repo, parentctx, ha, opts)
511 520 replacements.extend(replacement_)
512 521
513 522 hg.update(repo, parentctx.node())
514 523
515 524 mapping, tmpnodes, created, ntm = processreplacement(repo, replacements)
516 525 if mapping:
517 526 for prec, succs in mapping.iteritems():
518 527 if not succs:
519 528 ui.debug('histedit: %s is dropped\n' % node.short(prec))
520 529 else:
521 530 ui.debug('histedit: %s is replaced by %s\n' % (
522 531 node.short(prec), node.short(succs[0])))
523 532 if len(succs) > 1:
524 533 m = 'histedit: %s'
525 534 for n in succs[1:]:
526 535 ui.debug(m % node.short(n))
527 536
528 537 if not keep:
529 538 if mapping:
530 539 movebookmarks(ui, repo, mapping, topmost, ntm)
531 540 # TODO update mq state
532 541 if obsolete._enabled:
533 542 markers = []
534 543 # sort by revision number because it sound "right"
535 544 for prec in sorted(mapping, key=repo.changelog.rev):
536 545 succs = mapping[prec]
537 546 markers.append((repo[prec],
538 547 tuple(repo[s] for s in succs)))
539 548 if markers:
540 549 obsolete.createmarkers(repo, markers)
541 550 else:
542 551 cleanupnode(ui, repo, 'replaced', mapping)
543 552
544 553 cleanupnode(ui, repo, 'temp', tmpnodes)
545 554 os.unlink(os.path.join(repo.path, 'histedit-state'))
546 555 if os.path.exists(repo.sjoin('undo')):
547 556 os.unlink(repo.sjoin('undo'))
548 557
549 558
550 559 def bootstrapcontinue(ui, repo, parentctx, rules, opts):
551 560 action, currentnode = rules.pop(0)
552 561 ctx = repo[currentnode]
553 562 # is there any new commit between the expected parent and "."
554 563 #
555 564 # note: does not take non linear new change in account (but previous
556 565 # implementation didn't used them anyway (issue3655)
557 566 newchildren = [c.node() for c in repo.set('(%d::.)', parentctx)]
558 567 if not newchildren:
559 568 # `parentctxnode` should match but no result. This means that
560 569 # currentnode is not a descendant from parentctxnode.
561 570 msg = _('working directory parent is not a descendant of %s')
562 571 hint = _('update to %s or descendant and run "hg histedit '
563 572 '--continue" again') % parentctx
564 573 raise util.Abort(msg % parentctx, hint=hint)
565 574 newchildren.pop(0) # remove parentctxnode
566 575 # Commit dirty working directory if necessary
567 576 new = None
568 577 m, a, r, d = repo.status()[:4]
569 578 if m or a or r or d:
570 579 # prepare the message for the commit to comes
571 580 if action in ('f', 'fold'):
572 581 message = 'fold-temp-revision %s' % currentnode
573 582 else:
574 583 message = ctx.description() + '\n'
575 584 if action in ('e', 'edit', 'm', 'mess'):
576 585 editor = cmdutil.commitforceeditor
577 586 else:
578 587 editor = False
579 588 commit = commitfuncfor(repo, ctx)
580 589 new = commit(text=message, user=ctx.user(),
581 590 date=ctx.date(), extra=ctx.extra(),
582 591 editor=editor)
583 592 if new is not None:
584 593 newchildren.append(new)
585 594
586 595 replacements = []
587 596 # track replacements
588 597 if ctx.node() not in newchildren:
589 598 # note: new children may be empty when the changeset is dropped.
590 599 # this happen e.g during conflicting pick where we revert content
591 600 # to parent.
592 601 replacements.append((ctx.node(), tuple(newchildren)))
593 602
594 603 if action in ('f', 'fold'):
595 604 # finalize fold operation if applicable
596 605 if new is None:
597 606 new = newchildren[-1]
598 607 else:
599 608 newchildren.pop() # remove new from internal changes
600 609 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, opts,
601 610 newchildren)
602 611 replacements.extend(repl)
603 612 elif newchildren:
604 613 # otherwize update "parentctx" before proceding to further operation
605 614 parentctx = repo[newchildren[-1]]
606 615 return parentctx, replacements
607 616
608 617
609 618 def between(repo, old, new, keep):
610 619 """select and validate the set of revision to edit
611 620
612 621 When keep is false, the specified set can't have children."""
613 622 ctxs = list(repo.set('%n::%n', old, new))
614 623 if ctxs and not keep:
615 624 if (not obsolete._enabled and
616 625 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
617 626 raise util.Abort(_('cannot edit history that would orphan nodes'))
618 627 root = ctxs[0] # list is already sorted by repo.set
619 628 if not root.phase():
620 629 raise util.Abort(_('cannot edit immutable changeset: %s') % root)
621 630 return [c.node() for c in ctxs]
622 631
623 632
624 633 def writestate(repo, parentnode, rules, keep, topmost, replacements):
625 634 fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
626 635 pickle.dump((parentnode, rules, keep, topmost, replacements), fp)
627 636 fp.close()
628 637
629 638 def readstate(repo):
630 639 """Returns a tuple of (parentnode, rules, keep, topmost, replacements).
631 640 """
632 641 fp = open(os.path.join(repo.path, 'histedit-state'))
633 642 return pickle.load(fp)
634 643
635 644
636 645 def makedesc(c):
637 646 """build a initial action line for a ctx `c`
638 647
639 648 line are in the form:
640 649
641 650 pick <hash> <rev> <summary>
642 651 """
643 652 summary = ''
644 653 if c.description():
645 654 summary = c.description().splitlines()[0]
646 655 line = 'pick %s %d %s' % (c, c.rev(), summary)
647 656 return line[:80] # trim to 80 chars so it's not stupidly wide in my editor
648 657
649 658 def verifyrules(rules, repo, ctxs):
650 659 """Verify that there exists exactly one edit rule per given changeset.
651 660
652 661 Will abort if there are to many or too few rules, a malformed rule,
653 662 or a rule on a changeset outside of the user-given range.
654 663 """
655 664 parsed = []
656 665 if len(rules) != len(ctxs):
657 666 raise util.Abort(_('must specify a rule for each changeset once'))
658 667 for r in rules:
659 668 if ' ' not in r:
660 669 raise util.Abort(_('malformed line "%s"') % r)
661 670 action, rest = r.split(' ', 1)
662 671 if ' ' in rest.strip():
663 672 ha, rest = rest.split(' ', 1)
664 673 else:
665 674 ha = r.strip()
666 675 try:
667 676 if repo[ha] not in ctxs:
668 677 raise util.Abort(
669 678 _('may not use changesets other than the ones listed'))
670 679 except error.RepoError:
671 680 raise util.Abort(_('unknown changeset %s listed') % ha)
672 681 if action not in actiontable:
673 682 raise util.Abort(_('unknown action "%s"') % action)
674 683 parsed.append([action, ha])
675 684 return parsed
676 685
677 686 def processreplacement(repo, replacements):
678 687 """process the list of replacements to return
679 688
680 689 1) the final mapping between original and created nodes
681 690 2) the list of temporary node created by histedit
682 691 3) the list of new commit created by histedit"""
683 692 allsuccs = set()
684 693 replaced = set()
685 694 fullmapping = {}
686 695 # initialise basic set
687 696 # fullmapping record all operation recorded in replacement
688 697 for rep in replacements:
689 698 allsuccs.update(rep[1])
690 699 replaced.add(rep[0])
691 700 fullmapping.setdefault(rep[0], set()).update(rep[1])
692 701 new = allsuccs - replaced
693 702 tmpnodes = allsuccs & replaced
694 703 # Reduce content fullmapping into direct relation between original nodes
695 704 # and final node created during history edition
696 705 # Dropped changeset are replaced by an empty list
697 706 toproceed = set(fullmapping)
698 707 final = {}
699 708 while toproceed:
700 709 for x in list(toproceed):
701 710 succs = fullmapping[x]
702 711 for s in list(succs):
703 712 if s in toproceed:
704 713 # non final node with unknown closure
705 714 # We can't process this now
706 715 break
707 716 elif s in final:
708 717 # non final node, replace with closure
709 718 succs.remove(s)
710 719 succs.update(final[s])
711 720 else:
712 721 final[x] = succs
713 722 toproceed.remove(x)
714 723 # remove tmpnodes from final mapping
715 724 for n in tmpnodes:
716 725 del final[n]
717 726 # we expect all changes involved in final to exist in the repo
718 727 # turn `final` into list (topologically sorted)
719 728 nm = repo.changelog.nodemap
720 729 for prec, succs in final.items():
721 730 final[prec] = sorted(succs, key=nm.get)
722 731
723 732 # computed topmost element (necessary for bookmark)
724 733 if new:
725 734 newtopmost = sorted(new, key=repo.changelog.rev)[-1]
726 735 elif not final:
727 736 # Nothing rewritten at all. we won't need `newtopmost`
728 737 # It is the same as `oldtopmost` and `processreplacement` know it
729 738 newtopmost = None
730 739 else:
731 740 # every body died. The newtopmost is the parent of the root.
732 741 newtopmost = repo[sorted(final, key=repo.changelog.rev)[0]].p1().node()
733 742
734 743 return final, tmpnodes, new, newtopmost
735 744
736 745 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
737 746 """Move bookmark from old to newly created node"""
738 747 if not mapping:
739 748 # if nothing got rewritten there is not purpose for this function
740 749 return
741 750 moves = []
742 751 for bk, old in sorted(repo._bookmarks.iteritems()):
743 752 if old == oldtopmost:
744 753 # special case ensure bookmark stay on tip.
745 754 #
746 755 # This is arguably a feature and we may only want that for the
747 756 # active bookmark. But the behavior is kept compatible with the old
748 757 # version for now.
749 758 moves.append((bk, newtopmost))
750 759 continue
751 760 base = old
752 761 new = mapping.get(base, None)
753 762 if new is None:
754 763 continue
755 764 while not new:
756 765 # base is killed, trying with parent
757 766 base = repo[base].p1().node()
758 767 new = mapping.get(base, (base,))
759 768 # nothing to move
760 769 moves.append((bk, new[-1]))
761 770 if moves:
762 771 marks = repo._bookmarks
763 772 for mark, new in moves:
764 773 old = marks[mark]
765 774 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
766 775 % (mark, node.short(old), node.short(new)))
767 776 marks[mark] = new
768 777 marks.write()
769 778
770 779 def cleanupnode(ui, repo, name, nodes):
771 780 """strip a group of nodes from the repository
772 781
773 782 The set of node to strip may contains unknown nodes."""
774 783 ui.debug('should strip %s nodes %s\n' %
775 784 (name, ', '.join([node.short(n) for n in nodes])))
776 785 lock = None
777 786 try:
778 787 lock = repo.lock()
779 788 # Find all node that need to be stripped
780 789 # (we hg %lr instead of %ln to silently ignore unknown item
781 790 nm = repo.changelog.nodemap
782 791 nodes = [n for n in nodes if n in nm]
783 792 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
784 793 for c in roots:
785 794 # We should process node in reverse order to strip tip most first.
786 795 # but this trigger a bug in changegroup hook.
787 796 # This would reduce bundle overhead
788 797 repair.strip(ui, repo, c)
789 798 finally:
790 799 lockmod.release(lock)
@@ -1,179 +1,179 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > graphlog=
6 6 > histedit=
7 7 > EOF
8 8
9 9 $ hg init r
10 10 $ cd r
11 11
12 12 $ for x in a b c d e f ; do
13 13 > echo $x > $x
14 14 > hg add $x
15 15 > hg ci -m $x
16 16 > done
17 17
18 18 $ hg book -r 1 will-move-backwards
19 19 $ hg book -r 2 two
20 20 $ hg book -r 2 also-two
21 21 $ hg book -r 3 three
22 22 $ hg book -r 4 four
23 23 $ hg book -r tip five
24 24 $ hg log --graph
25 25 @ changeset: 5:652413bf663e
26 26 | bookmark: five
27 27 | tag: tip
28 28 | user: test
29 29 | date: Thu Jan 01 00:00:00 1970 +0000
30 30 | summary: f
31 31 |
32 32 o changeset: 4:e860deea161a
33 33 | bookmark: four
34 34 | user: test
35 35 | date: Thu Jan 01 00:00:00 1970 +0000
36 36 | summary: e
37 37 |
38 38 o changeset: 3:055a42cdd887
39 39 | bookmark: three
40 40 | user: test
41 41 | date: Thu Jan 01 00:00:00 1970 +0000
42 42 | summary: d
43 43 |
44 44 o changeset: 2:177f92b77385
45 45 | bookmark: also-two
46 46 | bookmark: two
47 47 | user: test
48 48 | date: Thu Jan 01 00:00:00 1970 +0000
49 49 | summary: c
50 50 |
51 51 o changeset: 1:d2ae7f538514
52 52 | bookmark: will-move-backwards
53 53 | user: test
54 54 | date: Thu Jan 01 00:00:00 1970 +0000
55 55 | summary: b
56 56 |
57 57 o changeset: 0:cb9a9f314b8b
58 58 user: test
59 59 date: Thu Jan 01 00:00:00 1970 +0000
60 60 summary: a
61 61
62 62 $ HGEDITOR=cat hg histedit 1
63 63 pick d2ae7f538514 1 b
64 64 pick 177f92b77385 2 c
65 65 pick 055a42cdd887 3 d
66 66 pick e860deea161a 4 e
67 67 pick 652413bf663e 5 f
68 68
69 69 # Edit history between d2ae7f538514 and 652413bf663e
70 70 #
71 71 # Commands:
72 72 # p, pick = use commit
73 73 # e, edit = use commit, but stop for amending
74 74 # f, fold = use commit, but fold into previous commit (combines N and N-1)
75 75 # d, drop = remove commit from history
76 76 # m, mess = edit message without changing commit content
77 77 #
78 78 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 79 $ cat >> commands.txt <<EOF
80 80 > pick 177f92b77385 2 c
81 81 > drop d2ae7f538514 1 b
82 82 > pick 055a42cdd887 3 d
83 83 > fold e860deea161a 4 e
84 84 > pick 652413bf663e 5 f
85 85 > EOF
86 86 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
87 histedit: moving bookmarks also-two from 177f92b77385 to d36c0562f908
88 histedit: moving bookmarks five from 652413bf663e to 0efacef7cb48
89 histedit: moving bookmarks four from e860deea161a to ae467701c500
90 histedit: moving bookmarks three from 055a42cdd887 to ae467701c500
91 histedit: moving bookmarks two from 177f92b77385 to d36c0562f908
87 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
88 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
89 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
90 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
91 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
92 92 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
93 93 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-backup.hg (glob)
94 saved backup bundle to $TESTTMP/r/.hg/strip-backup/34a9919932c1-backup.hg (glob)
94 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-backup.hg (glob)
95 95 $ hg log --graph
96 @ changeset: 3:0efacef7cb48
96 @ changeset: 3:cacdfd884a93
97 97 | bookmark: five
98 98 | tag: tip
99 99 | user: test
100 100 | date: Thu Jan 01 00:00:00 1970 +0000
101 101 | summary: f
102 102 |
103 o changeset: 2:ae467701c500
103 o changeset: 2:59d9f330561f
104 104 | bookmark: four
105 105 | bookmark: three
106 106 | user: test
107 107 | date: Thu Jan 01 00:00:00 1970 +0000
108 108 | summary: d
109 109 |
110 o changeset: 1:d36c0562f908
110 o changeset: 1:b346ab9a313d
111 111 | bookmark: also-two
112 112 | bookmark: two
113 113 | user: test
114 114 | date: Thu Jan 01 00:00:00 1970 +0000
115 115 | summary: c
116 116 |
117 117 o changeset: 0:cb9a9f314b8b
118 118 bookmark: will-move-backwards
119 119 user: test
120 120 date: Thu Jan 01 00:00:00 1970 +0000
121 121 summary: a
122 122
123 123 $ HGEDITOR=cat hg histedit 1
124 pick d36c0562f908 1 c
125 pick ae467701c500 2 d
126 pick 0efacef7cb48 3 f
124 pick b346ab9a313d 1 c
125 pick 59d9f330561f 2 d
126 pick cacdfd884a93 3 f
127 127
128 # Edit history between d36c0562f908 and 0efacef7cb48
128 # Edit history between b346ab9a313d and cacdfd884a93
129 129 #
130 130 # Commands:
131 131 # p, pick = use commit
132 132 # e, edit = use commit, but stop for amending
133 133 # f, fold = use commit, but fold into previous commit (combines N and N-1)
134 134 # d, drop = remove commit from history
135 135 # m, mess = edit message without changing commit content
136 136 #
137 137 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 138 $ cat > commands.txt << EOF
139 > pick d36c0562f908 1 c
140 > pick 0efacef7cb48 3 f
141 > pick ae467701c500 2 d
139 > pick b346ab9a313d 1 c
140 > pick cacdfd884a93 3 f
141 > pick 59d9f330561f 2 d
142 142 > EOF
143 143 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
144 histedit: moving bookmarks five from 0efacef7cb48 to 1be9c35b4cb2
145 histedit: moving bookmarks four from ae467701c500 to 1be9c35b4cb2
146 histedit: moving bookmarks three from ae467701c500 to 1be9c35b4cb2
147 saved backup bundle to $TESTTMP/r/.hg/strip-backup/ae467701c500-backup.hg (glob)
144 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
145 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
146 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
147 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-backup.hg (glob)
148 148
149 149 We expect 'five' to stay at tip, since the tipmost bookmark is most
150 150 likely the useful signal.
151 151
152 152 $ hg log --graph
153 @ changeset: 3:1be9c35b4cb2
153 @ changeset: 3:c04e50810e4b
154 154 | bookmark: five
155 155 | bookmark: four
156 156 | bookmark: three
157 157 | tag: tip
158 158 | user: test
159 159 | date: Thu Jan 01 00:00:00 1970 +0000
160 160 | summary: d
161 161 |
162 o changeset: 2:7c044e3e33a9
162 o changeset: 2:c13eb81022ca
163 163 | user: test
164 164 | date: Thu Jan 01 00:00:00 1970 +0000
165 165 | summary: f
166 166 |
167 o changeset: 1:d36c0562f908
167 o changeset: 1:b346ab9a313d
168 168 | bookmark: also-two
169 169 | bookmark: two
170 170 | user: test
171 171 | date: Thu Jan 01 00:00:00 1970 +0000
172 172 | summary: c
173 173 |
174 174 o changeset: 0:cb9a9f314b8b
175 175 bookmark: will-move-backwards
176 176 user: test
177 177 date: Thu Jan 01 00:00:00 1970 +0000
178 178 summary: a
179 179
@@ -1,359 +1,359 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > graphlog=
6 6 > histedit=
7 7 > EOF
8 8
9 9 $ EDITED="$TESTTMP/editedhistory"
10 10 $ cat > $EDITED <<EOF
11 11 > pick 177f92b77385 c
12 12 > pick e860deea161a e
13 13 > pick 652413bf663e f
14 14 > pick 055a42cdd887 d
15 15 > EOF
16 16 $ initrepo ()
17 17 > {
18 18 > hg init r
19 19 > cd r
20 20 > for x in a b c d e f ; do
21 21 > echo $x > $x
22 22 > hg add $x
23 23 > hg ci -m $x
24 24 > done
25 25 > }
26 26
27 27 $ initrepo
28 28
29 29 log before edit
30 30 $ hg log --graph
31 31 @ changeset: 5:652413bf663e
32 32 | tag: tip
33 33 | user: test
34 34 | date: Thu Jan 01 00:00:00 1970 +0000
35 35 | summary: f
36 36 |
37 37 o changeset: 4:e860deea161a
38 38 | user: test
39 39 | date: Thu Jan 01 00:00:00 1970 +0000
40 40 | summary: e
41 41 |
42 42 o changeset: 3:055a42cdd887
43 43 | user: test
44 44 | date: Thu Jan 01 00:00:00 1970 +0000
45 45 | summary: d
46 46 |
47 47 o changeset: 2:177f92b77385
48 48 | user: test
49 49 | date: Thu Jan 01 00:00:00 1970 +0000
50 50 | summary: c
51 51 |
52 52 o changeset: 1:d2ae7f538514
53 53 | user: test
54 54 | date: Thu Jan 01 00:00:00 1970 +0000
55 55 | summary: b
56 56 |
57 57 o changeset: 0:cb9a9f314b8b
58 58 user: test
59 59 date: Thu Jan 01 00:00:00 1970 +0000
60 60 summary: a
61 61
62 62
63 63 show the edit commands offered
64 64 $ HGEDITOR=cat hg histedit 177f92b77385
65 65 pick 177f92b77385 2 c
66 66 pick 055a42cdd887 3 d
67 67 pick e860deea161a 4 e
68 68 pick 652413bf663e 5 f
69 69
70 70 # Edit history between 177f92b77385 and 652413bf663e
71 71 #
72 72 # Commands:
73 73 # p, pick = use commit
74 74 # e, edit = use commit, but stop for amending
75 75 # f, fold = use commit, but fold into previous commit (combines N and N-1)
76 76 # d, drop = remove commit from history
77 77 # m, mess = edit message without changing commit content
78 78 #
79 79 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 80
81 81 edit the history
82 82 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
83 83 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
84 84 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 85 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 86 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 87
88 88 rules should end up in .hg/histedit-last-edit.txt:
89 89 $ cat .hg/histedit-last-edit.txt
90 90 pick 177f92b77385 c
91 91 pick e860deea161a e
92 92 pick 652413bf663e f
93 93 pick 055a42cdd887 d
94 94
95 95 log after edit
96 96 $ hg log --graph
97 @ changeset: 5:853c68da763f
97 @ changeset: 5:07114f51870f
98 98 | tag: tip
99 99 | user: test
100 100 | date: Thu Jan 01 00:00:00 1970 +0000
101 101 | summary: d
102 102 |
103 o changeset: 4:26f6a030ae82
103 o changeset: 4:8ade9693061e
104 104 | user: test
105 105 | date: Thu Jan 01 00:00:00 1970 +0000
106 106 | summary: f
107 107 |
108 o changeset: 3:b069cc29fb22
108 o changeset: 3:d8249471110a
109 109 | user: test
110 110 | date: Thu Jan 01 00:00:00 1970 +0000
111 111 | summary: e
112 112 |
113 113 o changeset: 2:177f92b77385
114 114 | user: test
115 115 | date: Thu Jan 01 00:00:00 1970 +0000
116 116 | summary: c
117 117 |
118 118 o changeset: 1:d2ae7f538514
119 119 | user: test
120 120 | date: Thu Jan 01 00:00:00 1970 +0000
121 121 | summary: b
122 122 |
123 123 o changeset: 0:cb9a9f314b8b
124 124 user: test
125 125 date: Thu Jan 01 00:00:00 1970 +0000
126 126 summary: a
127 127
128 128
129 129 put things back
130 130
131 131 $ cat > $EDITED <<EOF
132 132 > pick 177f92b77385 c
133 > pick 853c68da763f d
134 > pick b069cc29fb22 e
135 > pick 26f6a030ae82 f
133 > pick 07114f51870f d
134 > pick d8249471110a e
135 > pick 8ade9693061e f
136 136 > EOF
137 137 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
138 138 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
139 139 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 140 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 142
143 143 $ hg log --graph
144 @ changeset: 5:652413bf663e
144 @ changeset: 5:7eca9b5b1148
145 145 | tag: tip
146 146 | user: test
147 147 | date: Thu Jan 01 00:00:00 1970 +0000
148 148 | summary: f
149 149 |
150 o changeset: 4:e860deea161a
150 o changeset: 4:915da888f2de
151 151 | user: test
152 152 | date: Thu Jan 01 00:00:00 1970 +0000
153 153 | summary: e
154 154 |
155 o changeset: 3:055a42cdd887
155 o changeset: 3:10517e47bbbb
156 156 | user: test
157 157 | date: Thu Jan 01 00:00:00 1970 +0000
158 158 | summary: d
159 159 |
160 160 o changeset: 2:177f92b77385
161 161 | user: test
162 162 | date: Thu Jan 01 00:00:00 1970 +0000
163 163 | summary: c
164 164 |
165 165 o changeset: 1:d2ae7f538514
166 166 | user: test
167 167 | date: Thu Jan 01 00:00:00 1970 +0000
168 168 | summary: b
169 169 |
170 170 o changeset: 0:cb9a9f314b8b
171 171 user: test
172 172 date: Thu Jan 01 00:00:00 1970 +0000
173 173 summary: a
174 174
175 175
176 176 slightly different this time
177 177
178 178 $ cat > $EDITED <<EOF
179 > pick 055a42cdd887 d
180 > pick 652413bf663e f
181 > pick e860deea161a e
179 > pick 10517e47bbbb d
180 > pick 7eca9b5b1148 f
181 > pick 915da888f2de e
182 182 > pick 177f92b77385 c
183 183 > EOF
184 184 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
185 185 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
186 186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 187 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
188 188 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 190 $ hg log --graph
191 @ changeset: 5:99a62755c625
191 @ changeset: 5:38b92f448761
192 192 | tag: tip
193 193 | user: test
194 194 | date: Thu Jan 01 00:00:00 1970 +0000
195 195 | summary: c
196 196 |
197 o changeset: 4:7c6fdd608667
197 o changeset: 4:de71b079d9ce
198 198 | user: test
199 199 | date: Thu Jan 01 00:00:00 1970 +0000
200 200 | summary: e
201 201 |
202 o changeset: 3:c4f52e213402
202 o changeset: 3:be9ae3a309c6
203 203 | user: test
204 204 | date: Thu Jan 01 00:00:00 1970 +0000
205 205 | summary: f
206 206 |
207 o changeset: 2:bfe4a5a76b37
207 o changeset: 2:799205341b6b
208 208 | user: test
209 209 | date: Thu Jan 01 00:00:00 1970 +0000
210 210 | summary: d
211 211 |
212 212 o changeset: 1:d2ae7f538514
213 213 | user: test
214 214 | date: Thu Jan 01 00:00:00 1970 +0000
215 215 | summary: b
216 216 |
217 217 o changeset: 0:cb9a9f314b8b
218 218 user: test
219 219 date: Thu Jan 01 00:00:00 1970 +0000
220 220 summary: a
221 221
222 222
223 223 keep prevents stripping dead revs
224 224 $ cat > $EDITED <<EOF
225 > pick bfe4a5a76b37 d
226 > pick c4f52e213402 f
227 > pick 99a62755c625 c
228 > pick 7c6fdd608667 e
225 > pick 799205341b6b d
226 > pick be9ae3a309c6 f
227 > pick 38b92f448761 c
228 > pick de71b079d9ce e
229 229 > EOF
230 $ HGEDITOR="cat \"$EDITED\" > " hg histedit bfe4a5a76b37 --keep 2>&1 | fixbundle
230 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 799205341b6b --keep 2>&1 | fixbundle
231 231 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
232 232 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 233 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 234 $ hg log --graph
235 235 > cat > $EDITED <<EOF
236 > pick 7c6fdd608667 e
237 > pick 99a62755c625 c
236 > pick de71b079d9ce e
237 > pick 38b92f448761 c
238 238 > EOF
239 @ changeset: 7:99e266581538
239 @ changeset: 7:803ef1c6fcfd
240 240 | tag: tip
241 241 | user: test
242 242 | date: Thu Jan 01 00:00:00 1970 +0000
243 243 | summary: e
244 244 |
245 o changeset: 6:5ad36efb0653
246 | parent: 3:c4f52e213402
245 o changeset: 6:ece0b8d93dda
246 | parent: 3:be9ae3a309c6
247 247 | user: test
248 248 | date: Thu Jan 01 00:00:00 1970 +0000
249 249 | summary: c
250 250 |
251 | o changeset: 5:99a62755c625
251 | o changeset: 5:38b92f448761
252 252 | | user: test
253 253 | | date: Thu Jan 01 00:00:00 1970 +0000
254 254 | | summary: c
255 255 | |
256 | o changeset: 4:7c6fdd608667
256 | o changeset: 4:de71b079d9ce
257 257 |/ user: test
258 258 | date: Thu Jan 01 00:00:00 1970 +0000
259 259 | summary: e
260 260 |
261 o changeset: 3:c4f52e213402
261 o changeset: 3:be9ae3a309c6
262 262 | user: test
263 263 | date: Thu Jan 01 00:00:00 1970 +0000
264 264 | summary: f
265 265 |
266 o changeset: 2:bfe4a5a76b37
266 o changeset: 2:799205341b6b
267 267 | user: test
268 268 | date: Thu Jan 01 00:00:00 1970 +0000
269 269 | summary: d
270 270 |
271 271 o changeset: 1:d2ae7f538514
272 272 | user: test
273 273 | date: Thu Jan 01 00:00:00 1970 +0000
274 274 | summary: b
275 275 |
276 276 o changeset: 0:cb9a9f314b8b
277 277 user: test
278 278 date: Thu Jan 01 00:00:00 1970 +0000
279 279 summary: a
280 280
281 281
282 282 try with --rev
283 283 $ hg histedit --commands "$EDITED" --rev -2 2>&1 | fixbundle
284 284 abort: may not use changesets other than the ones listed
285 285 $ hg log --graph
286 @ changeset: 7:99e266581538
286 @ changeset: 7:803ef1c6fcfd
287 287 | tag: tip
288 288 | user: test
289 289 | date: Thu Jan 01 00:00:00 1970 +0000
290 290 | summary: e
291 291 |
292 o changeset: 6:5ad36efb0653
293 | parent: 3:c4f52e213402
292 o changeset: 6:ece0b8d93dda
293 | parent: 3:be9ae3a309c6
294 294 | user: test
295 295 | date: Thu Jan 01 00:00:00 1970 +0000
296 296 | summary: c
297 297 |
298 | o changeset: 5:99a62755c625
298 | o changeset: 5:38b92f448761
299 299 | | user: test
300 300 | | date: Thu Jan 01 00:00:00 1970 +0000
301 301 | | summary: c
302 302 | |
303 | o changeset: 4:7c6fdd608667
303 | o changeset: 4:de71b079d9ce
304 304 |/ user: test
305 305 | date: Thu Jan 01 00:00:00 1970 +0000
306 306 | summary: e
307 307 |
308 o changeset: 3:c4f52e213402
308 o changeset: 3:be9ae3a309c6
309 309 | user: test
310 310 | date: Thu Jan 01 00:00:00 1970 +0000
311 311 | summary: f
312 312 |
313 o changeset: 2:bfe4a5a76b37
313 o changeset: 2:799205341b6b
314 314 | user: test
315 315 | date: Thu Jan 01 00:00:00 1970 +0000
316 316 | summary: d
317 317 |
318 318 o changeset: 1:d2ae7f538514
319 319 | user: test
320 320 | date: Thu Jan 01 00:00:00 1970 +0000
321 321 | summary: b
322 322 |
323 323 o changeset: 0:cb9a9f314b8b
324 324 user: test
325 325 date: Thu Jan 01 00:00:00 1970 +0000
326 326 summary: a
327 327
328 328
329 329 should also work if a commit message is missing
330 330 $ BUNDLE="$TESTDIR/missing-comment.hg"
331 331 $ hg init missing
332 332 $ cd missing
333 333 $ hg unbundle $BUNDLE
334 334 adding changesets
335 335 adding manifests
336 336 adding file changes
337 337 added 3 changesets with 3 changes to 1 files
338 338 (run 'hg update' to get a working copy)
339 339 $ hg co tip
340 340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
341 341 $ hg log --graph
342 342 @ changeset: 2:bd22688093b3
343 343 | tag: tip
344 344 | user: Robert Altman <robert.altman@telventDTN.com>
345 345 | date: Mon Nov 28 16:40:04 2011 +0000
346 346 | summary: Update file.
347 347 |
348 348 o changeset: 1:3b3e956f9171
349 349 | user: Robert Altman <robert.altman@telventDTN.com>
350 350 | date: Mon Nov 28 16:37:57 2011 +0000
351 351 |
352 352 o changeset: 0:141947992243
353 353 user: Robert Altman <robert.altman@telventDTN.com>
354 354 date: Mon Nov 28 16:35:28 2011 +0000
355 355 summary: Checked in text file
356 356
357 357 $ hg histedit 0
358 358 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 359 $ cd ..
@@ -1,107 +1,126 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > graphlog=
6 6 > histedit=
7 7 > EOF
8 8
9 9 $ EDITED="$TESTTMP/editedhistory"
10 10 $ cat > $EDITED <<EOF
11 11 > drop 177f92b77385 c
12 12 > pick e860deea161a e
13 13 > pick 652413bf663e f
14 14 > pick 055a42cdd887 d
15 15 > EOF
16 16 $ initrepo ()
17 17 > {
18 18 > hg init r
19 19 > cd r
20 20 > for x in a b c d e f ; do
21 21 > echo $x > $x
22 22 > hg add $x
23 23 > hg ci -m $x
24 24 > done
25 25 > }
26 26
27 27 $ initrepo
28 28
29 29 log before edit
30 30 $ hg log --graph
31 31 @ changeset: 5:652413bf663e
32 32 | tag: tip
33 33 | user: test
34 34 | date: Thu Jan 01 00:00:00 1970 +0000
35 35 | summary: f
36 36 |
37 37 o changeset: 4:e860deea161a
38 38 | user: test
39 39 | date: Thu Jan 01 00:00:00 1970 +0000
40 40 | summary: e
41 41 |
42 42 o changeset: 3:055a42cdd887
43 43 | user: test
44 44 | date: Thu Jan 01 00:00:00 1970 +0000
45 45 | summary: d
46 46 |
47 47 o changeset: 2:177f92b77385
48 48 | user: test
49 49 | date: Thu Jan 01 00:00:00 1970 +0000
50 50 | summary: c
51 51 |
52 52 o changeset: 1:d2ae7f538514
53 53 | user: test
54 54 | date: Thu Jan 01 00:00:00 1970 +0000
55 55 | summary: b
56 56 |
57 57 o changeset: 0:cb9a9f314b8b
58 58 user: test
59 59 date: Thu Jan 01 00:00:00 1970 +0000
60 60 summary: a
61 61
62 62
63 63 edit the history
64 64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
65 65 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
66 66 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 67 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 68 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 69
70 70 log after edit
71 71 $ hg log --graph
72 @ changeset: 4:708943196e52
72 @ changeset: 4:f518305ce889
73 73 | tag: tip
74 74 | user: test
75 75 | date: Thu Jan 01 00:00:00 1970 +0000
76 76 | summary: d
77 77 |
78 o changeset: 3:75cbdffecadb
78 o changeset: 3:a4f7421b80f7
79 79 | user: test
80 80 | date: Thu Jan 01 00:00:00 1970 +0000
81 81 | summary: f
82 82 |
83 o changeset: 2:493dc0964412
83 o changeset: 2:ee283cb5f2d5
84 84 | user: test
85 85 | date: Thu Jan 01 00:00:00 1970 +0000
86 86 | summary: e
87 87 |
88 88 o changeset: 1:d2ae7f538514
89 89 | user: test
90 90 | date: Thu Jan 01 00:00:00 1970 +0000
91 91 | summary: b
92 92 |
93 93 o changeset: 0:cb9a9f314b8b
94 94 user: test
95 95 date: Thu Jan 01 00:00:00 1970 +0000
96 96 summary: a
97 97
98 98
99 Check histedit_source
100
101 $ hg log --debug --rev f518305ce889
102 changeset: 4:f518305ce889c07cb5bd05522176d75590ef3324
103 tag: tip
104 phase: draft
105 parent: 3:a4f7421b80f79fcc59fff01bcbf4a53d127dd6d3
106 parent: -1:0000000000000000000000000000000000000000
107 manifest: 4:d3d4f51c157ff242c32ff745d4799aaa26ccda44
108 user: test
109 date: Thu Jan 01 00:00:00 1970 +0000
110 files+: d
111 extra: branch=default
112 extra: histedit_source=055a42cdd88768532f9cf79daa407fc8d138de9b
113 description:
114 d
115
116
117
99 118 manifest after edit
100 119 $ hg manifest
101 120 a
102 121 b
103 122 d
104 123 e
105 124 f
106 125
107 126 $ cd ..
@@ -1,191 +1,211 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > graphlog=
6 6 > histedit=
7 7 > EOF
8 8
9 9 $ EDITED="$TESTTMP/editedhistory"
10 10 $ cat > $EDITED <<EOF
11 11 > pick 177f92b77385 c
12 12 > pick 055a42cdd887 d
13 13 > edit e860deea161a e
14 14 > pick 652413bf663e f
15 15 > EOF
16 16 $ initrepo ()
17 17 > {
18 18 > hg init r
19 19 > cd r
20 20 > for x in a b c d e f ; do
21 21 > echo $x > $x
22 22 > hg add $x
23 23 > hg ci -m $x
24 24 > done
25 25 > }
26 26
27 27 $ initrepo
28 28
29 29 log before edit
30 30 $ hg log --graph
31 31 @ changeset: 5:652413bf663e
32 32 | tag: tip
33 33 | user: test
34 34 | date: Thu Jan 01 00:00:00 1970 +0000
35 35 | summary: f
36 36 |
37 37 o changeset: 4:e860deea161a
38 38 | user: test
39 39 | date: Thu Jan 01 00:00:00 1970 +0000
40 40 | summary: e
41 41 |
42 42 o changeset: 3:055a42cdd887
43 43 | user: test
44 44 | date: Thu Jan 01 00:00:00 1970 +0000
45 45 | summary: d
46 46 |
47 47 o changeset: 2:177f92b77385
48 48 | user: test
49 49 | date: Thu Jan 01 00:00:00 1970 +0000
50 50 | summary: c
51 51 |
52 52 o changeset: 1:d2ae7f538514
53 53 | user: test
54 54 | date: Thu Jan 01 00:00:00 1970 +0000
55 55 | summary: b
56 56 |
57 57 o changeset: 0:cb9a9f314b8b
58 58 user: test
59 59 date: Thu Jan 01 00:00:00 1970 +0000
60 60 summary: a
61 61
62 62
63 63 edit the history
64 64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
65 65 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
66 66 abort: Make changes as needed, you may commit or record as needed now.
67 67 When you are finished, run hg histedit --continue to resume.
68 68
69 69 Go at a random point and try to continue
70 70
71 71 $ hg id -n
72 72 3+
73 73 $ hg up 0
74 74 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
75 75 $ HGEDITOR='echo foobaz > ' hg histedit --continue
76 76 abort: working directory parent is not a descendant of 055a42cdd887
77 77 (update to 055a42cdd887 or descendant and run "hg histedit --continue" again)
78 78 [255]
79 79 $ hg up 3
80 80 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 81
82 82 commit, then edit the revision
83 83 $ hg ci -m 'wat'
84 84 created new head
85 85 $ echo a > e
86 86 $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle
87 87 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 89
90 90 $ hg log --graph
91 @ changeset: 6:bf757c081cd0
91 @ changeset: 6:b5f70786f9b0
92 92 | tag: tip
93 93 | user: test
94 94 | date: Thu Jan 01 00:00:00 1970 +0000
95 95 | summary: f
96 96 |
97 o changeset: 5:d6b15fed32d4
97 o changeset: 5:a5e1ba2f7afb
98 98 | user: test
99 99 | date: Thu Jan 01 00:00:00 1970 +0000
100 100 | summary: foobaz
101 101 |
102 102 o changeset: 4:1a60820cd1f6
103 103 | user: test
104 104 | date: Thu Jan 01 00:00:00 1970 +0000
105 105 | summary: wat
106 106 |
107 107 o changeset: 3:055a42cdd887
108 108 | user: test
109 109 | date: Thu Jan 01 00:00:00 1970 +0000
110 110 | summary: d
111 111 |
112 112 o changeset: 2:177f92b77385
113 113 | user: test
114 114 | date: Thu Jan 01 00:00:00 1970 +0000
115 115 | summary: c
116 116 |
117 117 o changeset: 1:d2ae7f538514
118 118 | user: test
119 119 | date: Thu Jan 01 00:00:00 1970 +0000
120 120 | summary: b
121 121 |
122 122 o changeset: 0:cb9a9f314b8b
123 123 user: test
124 124 date: Thu Jan 01 00:00:00 1970 +0000
125 125 summary: a
126 126
127 127
128 128 $ hg cat e
129 129 a
130 130
131 check histedit_source
132
133 $ hg log --debug --rev 5
134 changeset: 5:a5e1ba2f7afb899ef1581cea528fd885d2fca70d
135 phase: draft
136 parent: 4:1a60820cd1f6004a362aa622ebc47d59bc48eb34
137 parent: -1:0000000000000000000000000000000000000000
138 manifest: 5:5ad3be8791f39117565557781f5464363b918a45
139 user: test
140 date: Thu Jan 01 00:00:00 1970 +0000
141 files: e
142 extra: branch=default
143 extra: histedit_source=e860deea161a2f77de56603b340ebbb4536308ae
144 description:
145 foobaz
146
147
148
131 149 $ cat > $EDITED <<EOF
132 > edit bf757c081cd0 f
150 > edit b5f70786f9b0 f
133 151 > EOF
134 152 $ HGEDITOR="cat \"$EDITED\" > " hg histedit tip 2>&1 | fixbundle
135 153 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
136 154 abort: Make changes as needed, you may commit or record as needed now.
137 155 When you are finished, run hg histedit --continue to resume.
138 156 $ hg status
139 157 A f
140 158 $ HGEDITOR='true' hg histedit --continue
141 159 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 saved backup bundle to $TESTTMP/r/.hg/strip-backup/b5f70786f9b0-backup.hg (glob)
161
142 162 $ hg status
143 163
144 164 log after edit
145 165 $ hg log --limit 1
146 changeset: 6:bf757c081cd0
166 changeset: 6:a107ee126658
147 167 tag: tip
148 168 user: test
149 169 date: Thu Jan 01 00:00:00 1970 +0000
150 170 summary: f
151 171
152 172
153 173 say we'll change the message, but don't.
154 174 $ cat > ../edit.sh <<EOF
155 175 > cat "\$1" | sed s/pick/mess/ > tmp
156 176 > mv tmp "\$1"
157 177 > EOF
158 178 $ HGEDITOR="sh ../edit.sh" hg histedit tip 2>&1 | fixbundle
159 179 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
160 180 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 181 $ hg status
162 182 $ hg log --limit 1
163 changeset: 6:bf757c081cd0
183 changeset: 6:1fd3b2fe7754
164 184 tag: tip
165 185 user: test
166 186 date: Thu Jan 01 00:00:00 1970 +0000
167 187 summary: f
168 188
169 189
170 190 modify the message
171 191 $ cat > $EDITED <<EOF
172 > mess bf757c081cd0 f
192 > mess 1fd3b2fe7754 f
173 193 > EOF
174 194 $ HGEDITOR="cat \"$EDITED\" > " hg histedit tip 2>&1 | fixbundle
175 195 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
176 196 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 197 $ hg status
178 198 $ hg log --limit 1
179 changeset: 6:0b16746f8e89
199 changeset: 6:5585e802ef99
180 200 tag: tip
181 201 user: test
182 202 date: Thu Jan 01 00:00:00 1970 +0000
183 summary: mess bf757c081cd0 f
203 summary: mess 1fd3b2fe7754 f
184 204
185 205
186 206 rollback should not work after a histedit
187 207 $ hg rollback
188 208 no rollback information available
189 209 [1]
190 210
191 211 $ cd ..
@@ -1,184 +1,184 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > graphlog=
6 6 > histedit=
7 7 > EOF
8 8
9 9 $ initrepo ()
10 10 > {
11 11 > hg init $1
12 12 > cd $1
13 13 > for x in a b c d e f ; do
14 14 > echo $x$x$x$x$x > $x
15 15 > hg add $x
16 16 > done
17 17 > hg ci -m 'Initial commit'
18 18 > for x in a b c d e f ; do
19 19 > echo $x > $x
20 20 > hg ci -m $x
21 21 > done
22 22 > echo 'I can haz no commute' > e
23 23 > hg ci -m 'does not commute with e'
24 24 > cd ..
25 25 > }
26 26
27 27 $ initrepo r
28 28 $ cd r
29 29 Initial generation of the command files
30 30
31 31 $ EDITED="$TESTTMP/editedhistory"
32 32 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
33 33 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
34 34 $ hg log --template 'fold {node|short} {rev} {desc}\n' -r 7 >> $EDITED
35 35 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
36 36 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
37 37 $ cat $EDITED
38 38 pick 65a9a84f33fd 3 c
39 39 pick 00f1c5383965 4 d
40 40 fold 39522b764e3d 7 does not commute with e
41 41 pick 7b4e2f4b7bcd 5 e
42 42 pick 500cac37a696 6 f
43 43
44 44 log before edit
45 45 $ hg log --graph
46 46 @ changeset: 7:39522b764e3d
47 47 | tag: tip
48 48 | user: test
49 49 | date: Thu Jan 01 00:00:00 1970 +0000
50 50 | summary: does not commute with e
51 51 |
52 52 o changeset: 6:500cac37a696
53 53 | user: test
54 54 | date: Thu Jan 01 00:00:00 1970 +0000
55 55 | summary: f
56 56 |
57 57 o changeset: 5:7b4e2f4b7bcd
58 58 | user: test
59 59 | date: Thu Jan 01 00:00:00 1970 +0000
60 60 | summary: e
61 61 |
62 62 o changeset: 4:00f1c5383965
63 63 | user: test
64 64 | date: Thu Jan 01 00:00:00 1970 +0000
65 65 | summary: d
66 66 |
67 67 o changeset: 3:65a9a84f33fd
68 68 | user: test
69 69 | date: Thu Jan 01 00:00:00 1970 +0000
70 70 | summary: c
71 71 |
72 72 o changeset: 2:da6535b52e45
73 73 | user: test
74 74 | date: Thu Jan 01 00:00:00 1970 +0000
75 75 | summary: b
76 76 |
77 77 o changeset: 1:c1f09da44841
78 78 | user: test
79 79 | date: Thu Jan 01 00:00:00 1970 +0000
80 80 | summary: a
81 81 |
82 82 o changeset: 0:1715188a53c7
83 83 user: test
84 84 date: Thu Jan 01 00:00:00 1970 +0000
85 85 summary: Initial commit
86 86
87 87
88 88 edit the history
89 89 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
90 90 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 91 merging e
92 92 warning: conflicts during merge.
93 93 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
94 94 abort: Fix up the change and run hg histedit --continue
95 95
96 96 fix up
97 97 $ echo 'I can haz no commute' > e
98 98 $ hg resolve --mark e
99 99 $ cat > cat.py <<EOF
100 100 > import sys
101 101 > print open(sys.argv[1]).read()
102 102 > print
103 103 > print
104 104 > EOF
105 105 $ HGEDITOR="python cat.py" hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
106 106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 107 d
108 108 ***
109 109 does not commute with e
110 110
111 111
112 112
113 113 HG: Enter commit message. Lines beginning with 'HG:' are removed.
114 114 HG: Leave message empty to abort commit.
115 115 HG: --
116 116 HG: user: test
117 117 HG: branch 'default'
118 118 HG: changed d
119 119 HG: changed e
120 120
121 121
122 122
123 123 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 124 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
125 125 merging e
126 126 warning: conflicts during merge.
127 127 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
128 128 abort: Fix up the change and run hg histedit --continue
129 129
130 130 just continue this time
131 131 $ hg revert -r 'p1()' e
132 132 $ hg resolve --mark e
133 133 $ hg histedit --continue 2>&1 | fixbundle
134 134 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 135 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
136 136
137 137 log after edit
138 138 $ hg log --graph
139 @ changeset: 5:2696a654c663
139 @ changeset: 5:d9cf42e54966
140 140 | tag: tip
141 141 | user: test
142 142 | date: Thu Jan 01 00:00:00 1970 +0000
143 143 | summary: f
144 144 |
145 o changeset: 4:ec2c1cf833a8
145 o changeset: 4:10486af2e984
146 146 | user: test
147 147 | date: Thu Jan 01 00:00:00 1970 +0000
148 148 | summary: d
149 149 |
150 150 o changeset: 3:65a9a84f33fd
151 151 | user: test
152 152 | date: Thu Jan 01 00:00:00 1970 +0000
153 153 | summary: c
154 154 |
155 155 o changeset: 2:da6535b52e45
156 156 | user: test
157 157 | date: Thu Jan 01 00:00:00 1970 +0000
158 158 | summary: b
159 159 |
160 160 o changeset: 1:c1f09da44841
161 161 | user: test
162 162 | date: Thu Jan 01 00:00:00 1970 +0000
163 163 | summary: a
164 164 |
165 165 o changeset: 0:1715188a53c7
166 166 user: test
167 167 date: Thu Jan 01 00:00:00 1970 +0000
168 168 summary: Initial commit
169 169
170 170
171 171 contents of e
172 172 $ hg cat e
173 173 I can haz no commute
174 174
175 175 manifest
176 176 $ hg manifest
177 177 a
178 178 b
179 179 c
180 180 d
181 181 e
182 182 f
183 183
184 184 $ cd ..
@@ -1,295 +1,317 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > graphlog=
6 6 > histedit=
7 7 > EOF
8 8
9 9 $ EDITED="$TESTTMP/editedhistory"
10 10 $ cat > $EDITED <<EOF
11 11 > pick e860deea161a e
12 12 > pick 652413bf663e f
13 13 > fold 177f92b77385 c
14 14 > pick 055a42cdd887 d
15 15 > EOF
16 16 $ initrepo ()
17 17 > {
18 18 > hg init r
19 19 > cd r
20 20 > for x in a b c d e f ; do
21 21 > echo $x > $x
22 22 > hg add $x
23 23 > hg ci -m $x
24 24 > done
25 25 > }
26 26
27 27 $ initrepo
28 28
29 29 log before edit
30 30 $ hg log --graph
31 31 @ changeset: 5:652413bf663e
32 32 | tag: tip
33 33 | user: test
34 34 | date: Thu Jan 01 00:00:00 1970 +0000
35 35 | summary: f
36 36 |
37 37 o changeset: 4:e860deea161a
38 38 | user: test
39 39 | date: Thu Jan 01 00:00:00 1970 +0000
40 40 | summary: e
41 41 |
42 42 o changeset: 3:055a42cdd887
43 43 | user: test
44 44 | date: Thu Jan 01 00:00:00 1970 +0000
45 45 | summary: d
46 46 |
47 47 o changeset: 2:177f92b77385
48 48 | user: test
49 49 | date: Thu Jan 01 00:00:00 1970 +0000
50 50 | summary: c
51 51 |
52 52 o changeset: 1:d2ae7f538514
53 53 | user: test
54 54 | date: Thu Jan 01 00:00:00 1970 +0000
55 55 | summary: b
56 56 |
57 57 o changeset: 0:cb9a9f314b8b
58 58 user: test
59 59 date: Thu Jan 01 00:00:00 1970 +0000
60 60 summary: a
61 61
62 62
63 63 edit the history
64 64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
65 65 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
66 66 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 67 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 68 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
69 69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 70 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 71 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
72 72
73 73 log after edit
74 74 $ hg log --graph
75 @ changeset: 4:82b0c1ff1777
75 @ changeset: 4:7e0a290363ed
76 76 | tag: tip
77 77 | user: test
78 78 | date: Thu Jan 01 00:00:00 1970 +0000
79 79 | summary: d
80 80 |
81 o changeset: 3:150aafb44a91
81 o changeset: 3:5e24935bad3d
82 82 | user: test
83 83 | date: Thu Jan 01 00:00:00 1970 +0000
84 84 | summary: pick e860deea161a e
85 85 |
86 o changeset: 2:493dc0964412
86 o changeset: 2:ee283cb5f2d5
87 87 | user: test
88 88 | date: Thu Jan 01 00:00:00 1970 +0000
89 89 | summary: e
90 90 |
91 91 o changeset: 1:d2ae7f538514
92 92 | user: test
93 93 | date: Thu Jan 01 00:00:00 1970 +0000
94 94 | summary: b
95 95 |
96 96 o changeset: 0:cb9a9f314b8b
97 97 user: test
98 98 date: Thu Jan 01 00:00:00 1970 +0000
99 99 summary: a
100 100
101 101
102 102 post-fold manifest
103 103 $ hg manifest
104 104 a
105 105 b
106 106 c
107 107 d
108 108 e
109 109 f
110 110
111
112 check histedit_source
113
114 $ hg log --debug --rev 3
115 changeset: 3:5e24935bad3d5a4486de3b90f233e991465ced72
116 phase: draft
117 parent: 2:ee283cb5f2d5955443f23a27b697a04339e9a39a
118 parent: -1:0000000000000000000000000000000000000000
119 manifest: 3:81eede616954057198ead0b2c73b41d1f392829a
120 user: test
121 date: Thu Jan 01 00:00:00 1970 +0000
122 files+: c f
123 extra: branch=default
124 extra: histedit_source=a4f7421b80f79fcc59fff01bcbf4a53d127dd6d3,177f92b773850b59254aa5e923436f921b55483b
125 description:
126 pick e860deea161a e
127 pick 652413bf663e f
128 fold 177f92b77385 c
129 pick 055a42cdd887 d
130
131
132
111 133 $ cd ..
112 134
113 135 folding and creating no new change doesn't break:
114 136 $ mkdir fold-to-empty-test
115 137 $ cd fold-to-empty-test
116 138 $ hg init
117 139 $ printf "1\n2\n3\n" > file
118 140 $ hg add file
119 141 $ hg commit -m '1+2+3'
120 142 $ echo 4 >> file
121 143 $ hg commit -m '+4'
122 144 $ echo 5 >> file
123 145 $ hg commit -m '+5'
124 146 $ echo 6 >> file
125 147 $ hg commit -m '+6'
126 148 $ hg log --graph
127 149 @ changeset: 3:251d831eeec5
128 150 | tag: tip
129 151 | user: test
130 152 | date: Thu Jan 01 00:00:00 1970 +0000
131 153 | summary: +6
132 154 |
133 155 o changeset: 2:888f9082bf99
134 156 | user: test
135 157 | date: Thu Jan 01 00:00:00 1970 +0000
136 158 | summary: +5
137 159 |
138 160 o changeset: 1:617f94f13c0f
139 161 | user: test
140 162 | date: Thu Jan 01 00:00:00 1970 +0000
141 163 | summary: +4
142 164 |
143 165 o changeset: 0:0189ba417d34
144 166 user: test
145 167 date: Thu Jan 01 00:00:00 1970 +0000
146 168 summary: 1+2+3
147 169
148 170
149 171 $ cat > editor.py <<EOF
150 172 > import re, sys
151 173 > rules = sys.argv[1]
152 174 > data = open(rules).read()
153 175 > data = re.sub(r'pick ([0-9a-f]{12} 2 \+5)', r'drop \1', data)
154 176 > data = re.sub(r'pick ([0-9a-f]{12} 2 \+6)', r'fold \1', data)
155 177 > open(rules, 'w').write(data)
156 178 > EOF
157 179
158 180 $ HGEDITOR='python editor.py' hg histedit 1
159 181 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 182 merging file
161 183 warning: conflicts during merge.
162 184 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
163 185 abort: Fix up the change and run hg histedit --continue
164 186 [255]
165 187 There were conflicts, we keep P1 content. This
166 188 should effectively drop the changes from +6.
167 189 $ hg status
168 190 M file
169 191 ? editor.py
170 192 ? file.orig
171 193 $ hg resolve -l
172 194 U file
173 195 $ hg revert -r 'p1()' file
174 196 $ hg resolve --mark file
175 197 $ hg histedit --continue
176 198 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 199 saved backup bundle to $TESTTMP/*-backup.hg (glob)
178 200 $ hg log --graph
179 201 @ changeset: 1:617f94f13c0f
180 202 | tag: tip
181 203 | user: test
182 204 | date: Thu Jan 01 00:00:00 1970 +0000
183 205 | summary: +4
184 206 |
185 207 o changeset: 0:0189ba417d34
186 208 user: test
187 209 date: Thu Jan 01 00:00:00 1970 +0000
188 210 summary: 1+2+3
189 211
190 212
191 213 $ cd ..
192 214
193 215 Test corner case where folded revision is separated from its parent by a
194 216 dropped revision.
195 217
196 218
197 219 $ hg init fold-with-dropped
198 220 $ cd fold-with-dropped
199 221 $ printf "1\n2\n3\n" > file
200 222 $ hg commit -Am '1+2+3'
201 223 adding file
202 224 $ echo 4 >> file
203 225 $ hg commit -m '+4'
204 226 $ echo 5 >> file
205 227 $ hg commit -m '+5'
206 228 $ echo 6 >> file
207 229 $ hg commit -m '+6'
208 230 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
209 231 @ 3:251d831eeec5 +6
210 232 |
211 233 o 2:888f9082bf99 +5
212 234 |
213 235 o 1:617f94f13c0f +4
214 236 |
215 237 o 0:0189ba417d34 1+2+3
216 238
217 239 $ EDITED="$TESTTMP/editcommands"
218 240 $ cat > $EDITED <<EOF
219 241 > pick 617f94f13c0f 1 +4
220 242 > drop 888f9082bf99 2 +5
221 243 > fold 251d831eeec5 3 +6
222 244 > EOF
223 245 $ HGEDITOR="cat $EDITED >" hg histedit 1
224 246 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
225 247 merging file
226 248 warning: conflicts during merge.
227 249 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
228 250 abort: Fix up the change and run hg histedit --continue
229 251 [255]
230 252 $ cat > file << EOF
231 253 > 1
232 254 > 2
233 255 > 3
234 256 > 4
235 257 > 5
236 258 > EOF
237 259 $ hg resolve --mark file
238 260 $ hg commit -m '+5.2'
239 261 created new head
240 262 $ echo 6 >> file
241 263 $ HGEDITOR=cat hg histedit --continue
242 264 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
243 265 +4
244 266 ***
245 267 +5.2
246 268 ***
247 269 +6
248 270
249 271
250 272
251 273 HG: Enter commit message. Lines beginning with 'HG:' are removed.
252 274 HG: Leave message empty to abort commit.
253 275 HG: --
254 276 HG: user: test
255 277 HG: branch 'default'
256 278 HG: changed file
257 279 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 280 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
259 281 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-backup.hg (glob)
260 282 $ hg log -G
261 @ changeset: 1:e29e02896e6c
283 @ changeset: 1:10c647b2cdd5
262 284 | tag: tip
263 285 | user: test
264 286 | date: Thu Jan 01 00:00:00 1970 +0000
265 287 | summary: +4
266 288 |
267 289 o changeset: 0:0189ba417d34
268 290 user: test
269 291 date: Thu Jan 01 00:00:00 1970 +0000
270 292 summary: 1+2+3
271 293
272 294 $ hg export tip
273 295 # HG changeset patch
274 296 # User test
275 297 # Date 0 0
276 # Node ID e29e02896e6c2b149d2228a0a64b4f3a9a4237f3
298 # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
277 299 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
278 300 +4
279 301 ***
280 302 +5.2
281 303 ***
282 304 +6
283 305
284 diff -r 0189ba417d34 -r e29e02896e6c file
306 diff -r 0189ba417d34 -r 10c647b2cdd5 file
285 307 --- a/file Thu Jan 01 00:00:00 1970 +0000
286 308 +++ b/file Thu Jan 01 00:00:00 1970 +0000
287 309 @@ -1,3 +1,6 @@
288 310 1
289 311 2
290 312 3
291 313 +4
292 314 +5
293 315 +6
294 316 $ cd ..
295 317
@@ -1,187 +1,191 b''
1 1 test for old histedit issue #6:
2 2 editing a changeset without any actual change would corrupt the repository
3 3
4 4 $ . "$TESTDIR/histedit-helpers.sh"
5 5
6 6 $ cat >> $HGRCPATH <<EOF
7 7 > [extensions]
8 8 > graphlog=
9 9 > histedit=
10 10 > EOF
11 11
12 12 $ initrepo ()
13 13 > {
14 14 > dir="$1"
15 15 > comment="$2"
16 16 > if [ -n "${comment}" ]; then
17 17 > echo % ${comment}
18 18 > echo % ${comment} | sed 's:.:-:g'
19 19 > fi
20 20 > hg init ${dir}
21 21 > cd ${dir}
22 22 > for x in a b c d e f ; do
23 23 > echo $x > $x
24 24 > hg add $x
25 25 > hg ci -m $x
26 26 > done
27 27 > cd ..
28 28 > }
29 29
30 30 $ geneditor ()
31 31 > {
32 32 > # generate an editor script for selecting changesets to be edited
33 33 > choice=$1 # changesets that should be edited (using sed line ranges)
34 34 > cat <<EOF | sed 's:^....::'
35 35 > # editing the rules, replacing 'pick' with 'edit' for the chosen lines
36 36 > sed '${choice}s:^pick:edit:' "\$1" > "\${1}.tmp"
37 37 > mv "\${1}.tmp" "\$1"
38 38 > # displaying the resulting rules, minus comments and empty lines
39 39 > sed '/^#/d;/^$/d;s:^:| :' "\$1" >&2
40 40 > EOF
41 41 > }
42 42
43 43 $ startediting ()
44 44 > {
45 45 > # begin an editing session
46 46 > choice="$1" # changesets that should be edited
47 47 > number="$2" # number of changesets considered (from tip)
48 48 > comment="$3"
49 49 > geneditor "${choice}" > edit.sh
50 50 > echo % start editing the history ${comment}
51 51 > HGEDITOR="sh ./edit.sh" hg histedit -- -${number} 2>&1 | fixbundle
52 52 > }
53 53
54 54 $ continueediting ()
55 55 > {
56 56 > # continue an edit already in progress
57 57 > editor="$1" # message editor when finalizing editing
58 58 > comment="$2"
59 59 > echo % finalize changeset editing ${comment}
60 60 > HGEDITOR=${editor} hg histedit --continue 2>&1 | fixbundle
61 61 > }
62 62
63 63 $ graphlog ()
64 64 > {
65 65 > comment="${1:-log}"
66 66 > echo % "${comment}"
67 67 > hg glog --template '{rev} {node} \"{desc|firstline}\"\n'
68 68 > }
69 69
70 70
71 71 $ initrepo r1 "test editing with no change"
72 72 % test editing with no change
73 73 -----------------------------
74 74 $ cd r1
75 75 $ graphlog "log before editing"
76 76 % log before editing
77 77 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
78 78 |
79 79 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
80 80 |
81 81 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
82 82 |
83 83 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
84 84 |
85 85 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
86 86 |
87 87 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
88 88
89 89 $ startediting 2 3 "(not changing anything)" # edit the 2nd of 3 changesets
90 90 % start editing the history (not changing anything)
91 91 | pick 055a42cdd887 3 d
92 92 | edit e860deea161a 4 e
93 93 | pick 652413bf663e 5 f
94 94 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
95 95 abort: Make changes as needed, you may commit or record as needed now.
96 96 When you are finished, run hg histedit --continue to resume.
97 97 $ continueediting true "(leaving commit message unaltered)"
98 98 % finalize changeset editing (leaving commit message unaltered)
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
101
100 102
101 103 check state of working copy
102 104 $ hg id
103 652413bf663e tip
105 794fe033d0a0 tip
104 106
105 107 $ graphlog "log after history editing"
106 108 % log after history editing
107 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
109 @ 5 794fe033d0a030f8df77c5de945fca35c9181c30 "f"
108 110 |
109 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
111 o 4 04d2fab980779f332dec458cc944f28de8b43435 "e"
110 112 |
111 113 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
112 114 |
113 115 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
114 116 |
115 117 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
116 118 |
117 119 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
118 120
119 121
120 122 $ cd ..
121 123
122 124 $ initrepo r2 "test editing with no change, then abort"
123 125 % test editing with no change, then abort
124 126 -----------------------------------------
125 127 $ cd r2
126 128 $ graphlog "log before editing"
127 129 % log before editing
128 130 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
129 131 |
130 132 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
131 133 |
132 134 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
133 135 |
134 136 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
135 137 |
136 138 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
137 139 |
138 140 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
139 141
140 142 $ startediting 1,2 3 "(not changing anything)" # edit the 1st two of 3 changesets
141 143 % start editing the history (not changing anything)
142 144 | edit 055a42cdd887 3 d
143 145 | edit e860deea161a 4 e
144 146 | pick 652413bf663e 5 f
145 147 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
146 148 abort: Make changes as needed, you may commit or record as needed now.
147 149 When you are finished, run hg histedit --continue to resume.
148 150 $ continueediting true "(leaving commit message unaltered)"
149 151 % finalize changeset editing (leaving commit message unaltered)
150 152 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 153 abort: Make changes as needed, you may commit or record as needed now.
152 154 When you are finished, run hg histedit --continue to resume.
153 155 $ graphlog "log after first edit"
154 156 % log after first edit
155 o 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
157 @ 6 e5ae3ca2f1ffdbd89ec41ebc273a231f7c3022f2 "d"
156 158 |
157 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
158 |
159 @ 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
160 |
159 | o 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
160 | |
161 | o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
162 | |
163 | o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
164 |/
161 165 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
162 166 |
163 167 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
164 168 |
165 169 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
166 170
167 171
168 172 abort editing session
169 173 $ hg histedit --abort 2>&1 | fixbundle
170 174 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 175
172 176 $ graphlog "log after abort"
173 177 % log after abort
174 178 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
175 179 |
176 180 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
177 181 |
178 182 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
179 183 |
180 184 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
181 185 |
182 186 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
183 187 |
184 188 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
185 189
186 190
187 191 $ cd ..
@@ -1,295 +1,295 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > graphlog=
6 6 > histedit=
7 7 > EOF
8 8
9 9 $ initrepo ()
10 10 > {
11 11 > hg init $1
12 12 > cd $1
13 13 > for x in a b c d e f ; do
14 14 > echo $x$x$x$x$x > $x
15 15 > hg add $x
16 16 > done
17 17 > hg ci -m 'Initial commit'
18 18 > for x in a b c d e f ; do
19 19 > echo $x > $x
20 20 > hg ci -m $x
21 21 > done
22 22 > echo 'I can haz no commute' > e
23 23 > hg ci -m 'does not commute with e'
24 24 > cd ..
25 25 > }
26 26
27 27 $ initrepo r1
28 28 $ cd r1
29 29
30 30 Initial generation of the command files
31 31
32 32 $ EDITED="$TESTTMP/editedhistory"
33 33 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
34 34 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
35 35 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 7 >> $EDITED
36 36 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
37 37 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
38 38 $ cat $EDITED
39 39 pick 65a9a84f33fd 3 c
40 40 pick 00f1c5383965 4 d
41 41 pick 39522b764e3d 7 does not commute with e
42 42 pick 7b4e2f4b7bcd 5 e
43 43 pick 500cac37a696 6 f
44 44
45 45 log before edit
46 46 $ hg log --graph
47 47 @ changeset: 7:39522b764e3d
48 48 | tag: tip
49 49 | user: test
50 50 | date: Thu Jan 01 00:00:00 1970 +0000
51 51 | summary: does not commute with e
52 52 |
53 53 o changeset: 6:500cac37a696
54 54 | user: test
55 55 | date: Thu Jan 01 00:00:00 1970 +0000
56 56 | summary: f
57 57 |
58 58 o changeset: 5:7b4e2f4b7bcd
59 59 | user: test
60 60 | date: Thu Jan 01 00:00:00 1970 +0000
61 61 | summary: e
62 62 |
63 63 o changeset: 4:00f1c5383965
64 64 | user: test
65 65 | date: Thu Jan 01 00:00:00 1970 +0000
66 66 | summary: d
67 67 |
68 68 o changeset: 3:65a9a84f33fd
69 69 | user: test
70 70 | date: Thu Jan 01 00:00:00 1970 +0000
71 71 | summary: c
72 72 |
73 73 o changeset: 2:da6535b52e45
74 74 | user: test
75 75 | date: Thu Jan 01 00:00:00 1970 +0000
76 76 | summary: b
77 77 |
78 78 o changeset: 1:c1f09da44841
79 79 | user: test
80 80 | date: Thu Jan 01 00:00:00 1970 +0000
81 81 | summary: a
82 82 |
83 83 o changeset: 0:1715188a53c7
84 84 user: test
85 85 date: Thu Jan 01 00:00:00 1970 +0000
86 86 summary: Initial commit
87 87
88 88
89 89 edit the history
90 90 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
91 91 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 92 merging e
93 93 warning: conflicts during merge.
94 94 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
95 95 abort: Fix up the change and run hg histedit --continue
96 96
97 97 abort the edit
98 98 $ hg histedit --abort 2>&1 | fixbundle
99 99 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 100
101 101
102 102 second edit set
103 103
104 104 $ hg log --graph
105 105 @ changeset: 7:39522b764e3d
106 106 | tag: tip
107 107 | user: test
108 108 | date: Thu Jan 01 00:00:00 1970 +0000
109 109 | summary: does not commute with e
110 110 |
111 111 o changeset: 6:500cac37a696
112 112 | user: test
113 113 | date: Thu Jan 01 00:00:00 1970 +0000
114 114 | summary: f
115 115 |
116 116 o changeset: 5:7b4e2f4b7bcd
117 117 | user: test
118 118 | date: Thu Jan 01 00:00:00 1970 +0000
119 119 | summary: e
120 120 |
121 121 o changeset: 4:00f1c5383965
122 122 | user: test
123 123 | date: Thu Jan 01 00:00:00 1970 +0000
124 124 | summary: d
125 125 |
126 126 o changeset: 3:65a9a84f33fd
127 127 | user: test
128 128 | date: Thu Jan 01 00:00:00 1970 +0000
129 129 | summary: c
130 130 |
131 131 o changeset: 2:da6535b52e45
132 132 | user: test
133 133 | date: Thu Jan 01 00:00:00 1970 +0000
134 134 | summary: b
135 135 |
136 136 o changeset: 1:c1f09da44841
137 137 | user: test
138 138 | date: Thu Jan 01 00:00:00 1970 +0000
139 139 | summary: a
140 140 |
141 141 o changeset: 0:1715188a53c7
142 142 user: test
143 143 date: Thu Jan 01 00:00:00 1970 +0000
144 144 summary: Initial commit
145 145
146 146
147 147 edit the history
148 148 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
149 149 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 150 merging e
151 151 warning: conflicts during merge.
152 152 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
153 153 abort: Fix up the change and run hg histedit --continue
154 154
155 155 fix up
156 156 $ echo 'I can haz no commute' > e
157 157 $ hg resolve --mark e
158 158 $ hg histedit --continue 2>&1 | fixbundle
159 159 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 160 merging e
161 161 warning: conflicts during merge.
162 162 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
163 163 abort: Fix up the change and run hg histedit --continue
164 164
165 165 This failure is caused by 7b4e2f4b7bcd "e" not rebasing the non commutative
166 166 former children.
167 167
168 168 just continue this time
169 169 $ hg revert -r 'p1()' e
170 170 $ hg resolve --mark e
171 171 $ hg histedit --continue 2>&1 | fixbundle
172 172 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 173 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 174
175 175 log after edit
176 176 $ hg log --graph
177 @ changeset: 6:8e082d1a72ea
177 @ changeset: 6:7efe1373e4bc
178 178 | tag: tip
179 179 | user: test
180 180 | date: Thu Jan 01 00:00:00 1970 +0000
181 181 | summary: f
182 182 |
183 o changeset: 5:13b04d775b81
183 o changeset: 5:e334d87a1e55
184 184 | user: test
185 185 | date: Thu Jan 01 00:00:00 1970 +0000
186 186 | summary: does not commute with e
187 187 |
188 188 o changeset: 4:00f1c5383965
189 189 | user: test
190 190 | date: Thu Jan 01 00:00:00 1970 +0000
191 191 | summary: d
192 192 |
193 193 o changeset: 3:65a9a84f33fd
194 194 | user: test
195 195 | date: Thu Jan 01 00:00:00 1970 +0000
196 196 | summary: c
197 197 |
198 198 o changeset: 2:da6535b52e45
199 199 | user: test
200 200 | date: Thu Jan 01 00:00:00 1970 +0000
201 201 | summary: b
202 202 |
203 203 o changeset: 1:c1f09da44841
204 204 | user: test
205 205 | date: Thu Jan 01 00:00:00 1970 +0000
206 206 | summary: a
207 207 |
208 208 o changeset: 0:1715188a53c7
209 209 user: test
210 210 date: Thu Jan 01 00:00:00 1970 +0000
211 211 summary: Initial commit
212 212
213 213
214 214 start over
215 215
216 216 $ cd ..
217 217
218 218 $ initrepo r2
219 219 $ cd r2
220 220 $ rm $EDITED
221 221 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
222 222 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
223 223 $ hg log --template 'mess {node|short} {rev} {desc}\n' -r 7 >> $EDITED
224 224 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
225 225 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
226 226 $ cat $EDITED
227 227 pick 65a9a84f33fd 3 c
228 228 pick 00f1c5383965 4 d
229 229 mess 39522b764e3d 7 does not commute with e
230 230 pick 7b4e2f4b7bcd 5 e
231 231 pick 500cac37a696 6 f
232 232
233 233 edit the history, this time with a fold action
234 234 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
235 235 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
236 236 merging e
237 237 warning: conflicts during merge.
238 238 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
239 239 abort: Fix up the change and run hg histedit --continue
240 240
241 241 $ echo 'I can haz no commute' > e
242 242 $ hg resolve --mark e
243 243 $ HGEDITOR="cat \"$EDITED\" > " hg histedit --continue 2>&1 | fixbundle
244 244 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 245 merging e
246 246 warning: conflicts during merge.
247 247 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
248 248 abort: Fix up the change and run hg histedit --continue
249 249 second edit also fails, but just continue
250 250 $ hg revert -r 'p1()' e
251 251 $ hg resolve --mark e
252 252 $ hg histedit --continue 2>&1 | fixbundle
253 253 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 254 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 255
256 256 post message fix
257 257 $ hg log --graph
258 @ changeset: 6:f14da722aa4b
258 @ changeset: 6:521c4c32c5e2
259 259 | tag: tip
260 260 | user: test
261 261 | date: Thu Jan 01 00:00:00 1970 +0000
262 262 | summary: f
263 263 |
264 o changeset: 5:382ff1adf0ed
264 o changeset: 5:f4f088e8adf6
265 265 | user: test
266 266 | date: Thu Jan 01 00:00:00 1970 +0000
267 267 | summary: pick 65a9a84f33fd 3 c
268 268 |
269 269 o changeset: 4:00f1c5383965
270 270 | user: test
271 271 | date: Thu Jan 01 00:00:00 1970 +0000
272 272 | summary: d
273 273 |
274 274 o changeset: 3:65a9a84f33fd
275 275 | user: test
276 276 | date: Thu Jan 01 00:00:00 1970 +0000
277 277 | summary: c
278 278 |
279 279 o changeset: 2:da6535b52e45
280 280 | user: test
281 281 | date: Thu Jan 01 00:00:00 1970 +0000
282 282 | summary: b
283 283 |
284 284 o changeset: 1:c1f09da44841
285 285 | user: test
286 286 | date: Thu Jan 01 00:00:00 1970 +0000
287 287 | summary: a
288 288 |
289 289 o changeset: 0:1715188a53c7
290 290 user: test
291 291 date: Thu Jan 01 00:00:00 1970 +0000
292 292 summary: Initial commit
293 293
294 294
295 295 $ cd ..
@@ -1,155 +1,155 b''
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 Enable obsolete
4 4
5 5 $ cat > ${TESTTMP}/obs.py << EOF
6 6 > import mercurial.obsolete
7 7 > mercurial.obsolete._enabled = True
8 8 > EOF
9 9
10 10 $ cat >> $HGRCPATH << EOF
11 11 > [ui]
12 12 > logtemplate= {rev}:{node|short} {desc|firstline}
13 13 > [phases]
14 14 > publish=False
15 15 > [extensions]'
16 16 > histedit=
17 17 >
18 18 > obs=${TESTTMP}/obs.py
19 19 > EOF
20 20
21 21 $ hg init base
22 22 $ cd base
23 23
24 24 $ for x in a b c d e f ; do
25 25 > echo $x > $x
26 26 > hg add $x
27 27 > hg ci -m $x
28 28 > done
29 29
30 30 $ hg log --graph
31 31 @ 5:652413bf663e f
32 32 |
33 33 o 4:e860deea161a e
34 34 |
35 35 o 3:055a42cdd887 d
36 36 |
37 37 o 2:177f92b77385 c
38 38 |
39 39 o 1:d2ae7f538514 b
40 40 |
41 41 o 0:cb9a9f314b8b a
42 42
43 43
44 44 $ HGEDITOR=cat hg histedit 1
45 45 pick d2ae7f538514 1 b
46 46 pick 177f92b77385 2 c
47 47 pick 055a42cdd887 3 d
48 48 pick e860deea161a 4 e
49 49 pick 652413bf663e 5 f
50 50
51 51 # Edit history between d2ae7f538514 and 652413bf663e
52 52 #
53 53 # Commands:
54 54 # p, pick = use commit
55 55 # e, edit = use commit, but stop for amending
56 56 # f, fold = use commit, but fold into previous commit (combines N and N-1)
57 57 # d, drop = remove commit from history
58 58 # m, mess = edit message without changing commit content
59 59 #
60 60 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 61 $ cat > commands.txt <<EOF
62 62 > pick 177f92b77385 2 c
63 63 > drop d2ae7f538514 1 b
64 64 > pick 055a42cdd887 3 d
65 65 > fold e860deea161a 4 e
66 66 > pick 652413bf663e 5 f
67 67 > EOF
68 68 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
69 saved backup bundle to $TESTTMP/base/.hg/strip-backup/34a9919932c1-backup.hg (glob)
69 saved backup bundle to $TESTTMP/base/.hg/strip-backup/96e494a2d553-backup.hg (glob)
70 70 $ hg log --graph --hidden
71 @ 8:0efacef7cb48 f
71 @ 8:cacdfd884a93 f
72 72 |
73 o 7:ae467701c500 d
73 o 7:59d9f330561f d
74 74 |
75 o 6:d36c0562f908 c
75 o 6:b346ab9a313d c
76 76 |
77 77 | x 5:652413bf663e f
78 78 | |
79 79 | x 4:e860deea161a e
80 80 | |
81 81 | x 3:055a42cdd887 d
82 82 | |
83 83 | x 2:177f92b77385 c
84 84 | |
85 85 | x 1:d2ae7f538514 b
86 86 |/
87 87 o 0:cb9a9f314b8b a
88 88
89 89 $ hg debugobsolete
90 90 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {'date': '* *', 'user': 'test'} (glob)
91 177f92b773850b59254aa5e923436f921b55483b d36c0562f908c692f5204d606d4ff3537d41f1bf 0 {'date': '* *', 'user': 'test'} (glob)
92 055a42cdd88768532f9cf79daa407fc8d138de9b ae467701c5006bf21ffcfdb555b3d6b63280b6b7 0 {'date': '* *', 'user': 'test'} (glob)
93 e860deea161a2f77de56603b340ebbb4536308ae ae467701c5006bf21ffcfdb555b3d6b63280b6b7 0 {'date': '* *', 'user': 'test'} (glob)
94 652413bf663ef2a641cab26574e46d5f5a64a55a 0efacef7cb481bf574f69075b82d044fdbe5c20f 0 {'date': '* *', 'user': 'test'} (glob)
91 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 {'date': '* *', 'user': 'test'} (glob)
92 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
93 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
94 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 {'date': '* *', 'user': 'test'} (glob)
95 95
96 96
97 97 Ensure hidden revision does not prevent histedit
98 98 -------------------------------------------------
99 99
100 100 create an hidden revision
101 101
102 102 $ cat > commands.txt <<EOF
103 > pick d36c0562f908 6 c
104 > drop ae467701c500 7 d
105 > pick 0efacef7cb48 8 f
103 > pick b346ab9a313d 6 c
104 > drop 59d9f330561f 7 d
105 > pick cacdfd884a93 8 f
106 106 > EOF
107 107 $ hg histedit 6 --commands commands.txt
108 108 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
109 109 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 110 $ hg log --graph
111 @ 9:7c044e3e33a9 f
111 @ 9:c13eb81022ca f
112 112 |
113 o 6:d36c0562f908 c
113 o 6:b346ab9a313d c
114 114 |
115 115 o 0:cb9a9f314b8b a
116 116
117 117 check hidden revision are ignored (6 have hidden children 7 and 8)
118 118
119 119 $ cat > commands.txt <<EOF
120 > pick d36c0562f908 6 c
121 > pick 7c044e3e33a9 8 f
120 > pick b346ab9a313d 6 c
121 > pick c13eb81022ca 8 f
122 122 > EOF
123 123 $ hg histedit 6 --commands commands.txt
124 124 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
125 125
126 126
127 127 Check that histedit respect phases
128 128 =========================================
129 129
130 130 (not directly related to the test file but doesn't deserve it's own test case)
131 131
132 132 $ hg log -G
133 @ 9:7c044e3e33a9 f
133 @ 9:c13eb81022ca f
134 134 |
135 o 6:d36c0562f908 c
135 o 6:b346ab9a313d c
136 136 |
137 137 o 0:cb9a9f314b8b a
138 138
139 139 $ hg ph -pv '.^'
140 140 phase changed for 2 changesets
141 141 $ hg histedit -r '.~2'
142 142 abort: cannot edit immutable changeset: cb9a9f314b8b
143 143 [255]
144 144
145 145
146 146 Test that rewriting leaving instability behind is allowed
147 147 ---------------------------------------------------------------------
148 148
149 149 $ hg up '.^'
150 150 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
151 151 $ hg phase --force --draft .
152 152 $ hg log -r 'children(.)'
153 9:7c044e3e33a9 f (no-eol)
153 9:c13eb81022ca f (no-eol)
154 154 $ hg histedit -r '.'
155 155 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
General Comments 0
You need to be logged in to leave comments. Login now