Mercurial > hg
comparison hgext/rebase.py @ 18755:72412afe4c28 stable
rebase: restore active bookmark after rebase --continue
When a rebase has conflicts and the user uses rebase --continue, the previously
active bookmark was not being made active once again. With this change that
bookmark is made active again, just as if the rebase had never been interrupted.
This changes the rebasestate file format, but should handle old formats correctly.
Since the file is transient, this is even less of a problem.
Adds a test to verify the new behavior. I manually tested continuing rebases
with and without an active bookmark, and with and without being on the bookmark
being rebased.
author | Durham Goode <durham@fb.com> |
---|---|
date | Mon, 11 Mar 2013 15:37:28 -0700 |
parents | 12de53323e59 |
children | 249b6b455e9b |
comparison
equal
deleted
inserted
replaced
18754:d420ac09f866 | 18755:72412afe4c28 |
---|---|
110 continued with --continue/-c or aborted with --abort/-a. | 110 continued with --continue/-c or aborted with --abort/-a. |
111 | 111 |
112 Returns 0 on success, 1 if nothing to rebase. | 112 Returns 0 on success, 1 if nothing to rebase. |
113 """ | 113 """ |
114 originalwd = target = None | 114 originalwd = target = None |
115 activebookmark = None | |
115 external = nullrev | 116 external = nullrev |
116 state = {} | 117 state = {} |
117 skipped = set() | 118 skipped = set() |
118 targetancestors = set() | 119 targetancestors = set() |
119 | 120 |
157 _('abort and continue do not allow specifying revisions')) | 158 _('abort and continue do not allow specifying revisions')) |
158 if opts.get('tool', False): | 159 if opts.get('tool', False): |
159 ui.warn(_('tool option will be ignored\n')) | 160 ui.warn(_('tool option will be ignored\n')) |
160 | 161 |
161 (originalwd, target, state, skipped, collapsef, keepf, | 162 (originalwd, target, state, skipped, collapsef, keepf, |
162 keepbranchesf, external) = restorestatus(repo) | 163 keepbranchesf, external, activebookmark) = restorestatus(repo) |
163 if abortf: | 164 if abortf: |
164 return abort(repo, originalwd, target, state) | 165 return abort(repo, originalwd, target, state) |
165 else: | 166 else: |
166 if srcf and basef: | 167 if srcf and basef: |
167 raise util.Abort(_('cannot specify both a ' | 168 raise util.Abort(_('cannot specify both a ' |
243 if not targetancestors: | 244 if not targetancestors: |
244 targetancestors = repo.changelog.ancestors([target], inclusive=True) | 245 targetancestors = repo.changelog.ancestors([target], inclusive=True) |
245 | 246 |
246 # Keep track of the current bookmarks in order to reset them later | 247 # Keep track of the current bookmarks in order to reset them later |
247 currentbookmarks = repo._bookmarks.copy() | 248 currentbookmarks = repo._bookmarks.copy() |
248 activebookmark = repo._bookmarkcurrent | 249 activebookmark = activebookmark or repo._bookmarkcurrent |
249 if activebookmark: | 250 if activebookmark: |
250 bookmarks.unsetcurrent(repo) | 251 bookmarks.unsetcurrent(repo) |
251 | 252 |
252 sortedstate = sorted(state) | 253 sortedstate = sorted(state) |
253 total = len(sortedstate) | 254 total = len(sortedstate) |
256 pos += 1 | 257 pos += 1 |
257 if state[rev] == -1: | 258 if state[rev] == -1: |
258 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])), | 259 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])), |
259 _('changesets'), total) | 260 _('changesets'), total) |
260 storestatus(repo, originalwd, target, state, collapsef, keepf, | 261 storestatus(repo, originalwd, target, state, collapsef, keepf, |
261 keepbranchesf, external) | 262 keepbranchesf, external, activebookmark) |
262 p1, p2 = defineparents(repo, rev, target, state, | 263 p1, p2 = defineparents(repo, rev, target, state, |
263 targetancestors) | 264 targetancestors) |
264 if len(repo.parents()) == 2: | 265 if len(repo.parents()) == 2: |
265 repo.ui.debug('resuming interrupted rebase\n') | 266 repo.ui.debug('resuming interrupted rebase\n') |
266 else: | 267 else: |
514 bookmarks.deletedivergent(repo, [targetnode], k) | 515 bookmarks.deletedivergent(repo, [targetnode], k) |
515 | 516 |
516 marks.write() | 517 marks.write() |
517 | 518 |
518 def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches, | 519 def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches, |
519 external): | 520 external, activebookmark): |
520 'Store the current status to allow recovery' | 521 'Store the current status to allow recovery' |
521 f = repo.opener("rebasestate", "w") | 522 f = repo.opener("rebasestate", "w") |
522 f.write(repo[originalwd].hex() + '\n') | 523 f.write(repo[originalwd].hex() + '\n') |
523 f.write(repo[target].hex() + '\n') | 524 f.write(repo[target].hex() + '\n') |
524 f.write(repo[external].hex() + '\n') | 525 f.write(repo[external].hex() + '\n') |
525 f.write('%d\n' % int(collapse)) | 526 f.write('%d\n' % int(collapse)) |
526 f.write('%d\n' % int(keep)) | 527 f.write('%d\n' % int(keep)) |
527 f.write('%d\n' % int(keepbranches)) | 528 f.write('%d\n' % int(keepbranches)) |
529 f.write('%s\n' % (activebookmark or '')) | |
528 for d, v in state.iteritems(): | 530 for d, v in state.iteritems(): |
529 oldrev = repo[d].hex() | 531 oldrev = repo[d].hex() |
530 if v > nullmerge: | 532 if v > nullmerge: |
531 newrev = repo[v].hex() | 533 newrev = repo[v].hex() |
532 else: | 534 else: |
543 'Restore a previously stored status' | 545 'Restore a previously stored status' |
544 try: | 546 try: |
545 target = None | 547 target = None |
546 collapse = False | 548 collapse = False |
547 external = nullrev | 549 external = nullrev |
550 activebookmark = None | |
548 state = {} | 551 state = {} |
549 f = repo.opener("rebasestate") | 552 f = repo.opener("rebasestate") |
550 for i, l in enumerate(f.read().splitlines()): | 553 for i, l in enumerate(f.read().splitlines()): |
551 if i == 0: | 554 if i == 0: |
552 originalwd = repo[l].rev() | 555 originalwd = repo[l].rev() |
558 collapse = bool(int(l)) | 561 collapse = bool(int(l)) |
559 elif i == 4: | 562 elif i == 4: |
560 keep = bool(int(l)) | 563 keep = bool(int(l)) |
561 elif i == 5: | 564 elif i == 5: |
562 keepbranches = bool(int(l)) | 565 keepbranches = bool(int(l)) |
566 elif i == 6 and not (len(l) == 81 and ':' in l): | |
567 # line 6 is a recent addition, so for backwards compatibility | |
568 # check that the line doesn't look like the oldrev:newrev lines | |
569 activebookmark = l | |
563 else: | 570 else: |
564 oldrev, newrev = l.split(':') | 571 oldrev, newrev = l.split(':') |
565 if newrev in (str(nullmerge), str(revignored)): | 572 if newrev in (str(nullmerge), str(revignored)): |
566 state[repo[oldrev].rev()] = int(newrev) | 573 state[repo[oldrev].rev()] = int(newrev) |
567 else: | 574 else: |
575 skipped.add(old) | 582 skipped.add(old) |
576 seen.add(new) | 583 seen.add(new) |
577 repo.ui.debug('computed skipped revs: %s\n' % skipped) | 584 repo.ui.debug('computed skipped revs: %s\n' % skipped) |
578 repo.ui.debug('rebase status resumed\n') | 585 repo.ui.debug('rebase status resumed\n') |
579 return (originalwd, target, state, skipped, | 586 return (originalwd, target, state, skipped, |
580 collapse, keep, keepbranches, external) | 587 collapse, keep, keepbranches, external, activebookmark) |
581 except IOError, err: | 588 except IOError, err: |
582 if err.errno != errno.ENOENT: | 589 if err.errno != errno.ENOENT: |
583 raise | 590 raise |
584 raise util.Abort(_('no rebase in progress')) | 591 raise util.Abort(_('no rebase in progress')) |
585 | 592 |