comparison hgext/histedit.py @ 24771:3133e246c912

histedit: convert fold/roll actions into a class This converts the fold/roll actions into a histeditclass instance, as part of an ongoing effort to refactor histedit for maintainability and robustness. The tests changed for two reasons: 1) We get a new 'empty changeset' warning because we now warn more consistently between normal histedit and --continue about commits disappearing. 2) Previously we were not putting the histedit-source extra field on the temporary fold commit during normal runs, but we were on --continue runs. By unifying these code paths we now consistently put histedit-source on the temporary fold commit, which changes some of the hashes in the backup bundles.
author Durham Goode <durham@fb.com>
date Sat, 04 Apr 2015 02:03:27 -0700
parents facdb20e60e9
children 8f6494eb16eb
comparison
equal deleted inserted replaced
24770:facdb20e60e9 24771:3133e246c912
508 'resume.')) 508 'resume.'))
509 509
510 def commiteditor(self): 510 def commiteditor(self):
511 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit') 511 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit')
512 512
513 def rollup(ui, state, ha, opts): 513 class fold(histeditaction):
514 rollupopts = opts.copy() 514 def continuedirty(self):
515 rollupopts['rollup'] = True 515 repo = self.repo
516 return fold(ui, state, ha, rollupopts) 516 rulectx = repo[self.node]
517 517
518 def fold(ui, state, ha, opts): 518 commit = commitfuncfor(repo, rulectx)
519 repo, ctxnode = state.repo, state.parentctxnode 519 commit(text='fold-temp-revision %s' % node.short(self.node),
520 ctx = repo[ctxnode] 520 user=rulectx.user(), date=rulectx.date(),
521 oldctx = repo[ha] 521 extra=rulectx.extra())
522 hg.update(repo, ctx.node()) 522
523 stats = applychanges(ui, repo, oldctx, opts) 523 def continueclean(self):
524 if stats and stats[3] > 0: 524 repo = self.repo
525 raise error.InterventionRequired( 525 ctx = repo['.']
526 _('Fix up the change and run hg histedit --continue')) 526 rulectx = repo[self.node]
527 n = repo.commit(text='fold-temp-revision %s' % ha[:12], user=oldctx.user(), 527 parentctxnode = self.state.parentctxnode
528 date=oldctx.date(), extra=oldctx.extra()) 528 if ctx.node() == parentctxnode:
529 if n is None: 529 repo.ui.warn(_('%s: empty changeset\n') %
530 ui.warn(_('%s: empty changeset') % ha[:12]) 530 node.short(self.node))
531 return ctx, [] 531 return ctx, [(self.node, (parentctxnode,))]
532 return finishfold(ui, repo, ctx, oldctx, n, opts, []) 532
533 parentctx = repo[parentctxnode]
534 newcommits = set(c.node() for c in repo.set('(%d::. - %d)', parentctx,
535 parentctx))
536 if not newcommits:
537 repo.ui.warn(_('%s: cannot fold - working copy is not a '
538 'descendant of previous commit %s\n') %
539 (node.short(self.node), node.short(parentctxnode)))
540 return ctx, [(self.node, (ctx.node(),))]
541
542 middlecommits = newcommits.copy()
543 middlecommits.discard(ctx.node())
544
545 foldopts = {}
546 if isinstance(self, rollup):
547 foldopts['rollup'] = True
548
549 return finishfold(repo.ui, repo, parentctx, rulectx, ctx.node(),
550 foldopts, middlecommits)
551
552 class rollup(fold):
553 pass
533 554
534 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges): 555 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
535 parent = ctx.parents()[0].node() 556 parent = ctx.parents()[0].node()
536 hg.update(repo, parent) 557 hg.update(repo, parent)
537 ### prepare new commit data 558 ### prepare new commit data
905 newchildren = gatherchildren(repo, parentctx) 926 newchildren = gatherchildren(repo, parentctx)
906 # Commit dirty working directory if necessary 927 # Commit dirty working directory if necessary
907 new = None 928 new = None
908 if s.modified or s.added or s.removed or s.deleted: 929 if s.modified or s.added or s.removed or s.deleted:
909 # prepare the message for the commit to comes 930 # prepare the message for the commit to comes
910 if action in ('f', 'fold', 'r', 'roll'): 931 message = ctx.description()
911 message = 'fold-temp-revision %s' % currentnode[:12]
912 else:
913 message = ctx.description()
914 editor = cmdutil.getcommiteditor() 932 editor = cmdutil.getcommiteditor()
915 commit = commitfuncfor(repo, ctx) 933 commit = commitfuncfor(repo, ctx)
916 new = commit(text=message, user=ctx.user(), date=ctx.date(), 934 new = commit(text=message, user=ctx.user(), date=ctx.date(),
917 extra=ctx.extra(), editor=editor) 935 extra=ctx.extra(), editor=editor)
918 if new is not None: 936 if new is not None:
923 # note: new children may be empty when the changeset is dropped. 941 # note: new children may be empty when the changeset is dropped.
924 # this happen e.g during conflicting pick where we revert content 942 # this happen e.g during conflicting pick where we revert content
925 # to parent. 943 # to parent.
926 replacements.append((ctx.node(), tuple(newchildren))) 944 replacements.append((ctx.node(), tuple(newchildren)))
927 945
928 if action in ('f', 'fold', 'r', 'roll'): 946 if newchildren:
929 if newchildren:
930 # finalize fold operation if applicable
931 if new is None:
932 new = newchildren[-1]
933 else:
934 newchildren.pop() # remove new from internal changes
935 foldopts = opts
936 if action in ('r', 'roll'):
937 foldopts = foldopts.copy()
938 foldopts['rollup'] = True
939 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new,
940 foldopts, newchildren)
941 replacements.extend(repl)
942 else:
943 # newchildren is empty if the fold did not result in any commit
944 # this happen when all folded change are discarded during the
945 # merge.
946 replacements.append((ctx.node(), (parentctx.node(),)))
947 elif newchildren:
948 # otherwise update "parentctx" before proceeding further 947 # otherwise update "parentctx" before proceeding further
949 parentctx = repo[newchildren[-1]] 948 parentctx = repo[newchildren[-1]]
950 949
951 state.parentctxnode = parentctx.node() 950 state.parentctxnode = parentctx.node()
952 state.replacements.extend(replacements) 951 state.replacements.extend(replacements)