# HG changeset patch # User Durham Goode # Date 1428172493 25200 # Node ID bdf84cc2115bbe4bed0cf87cf7da2576faef08b1 # Parent 4dcd55802237ad52bb0fab856c185250ccd31f13 histedit: add a new histeditaction class This adds a new class called histeditaction. It represents a single action in a histedit plan. Future patches will integrate it into the histedit flow, then convert each existing action in to the class form one by one. This is part of a larger refactor aimed at increasing histedit robustness, maintainability, and extensibility. diff -r 4dcd55802237 -r bdf84cc2115b hgext/histedit.py --- a/hgext/histedit.py Sat Apr 04 01:00:05 2015 -0700 +++ b/hgext/histedit.py Sat Apr 04 11:34:53 2015 -0700 @@ -304,6 +304,72 @@ def clear(self): self.repo.vfs.unlink('histedit-state') +class histeditaction(object): + def __init__(self, state, node): + self.state = state + self.repo = state.repo + self.node = node + + @classmethod + def fromrule(cls, state, rule): + """Parses the given rule, returning an instance of the histeditaction. + """ + repo = state.repo + rulehash = rule.strip().split(' ', 1)[0] + try: + node = repo[rulehash].node() + except error.RepoError: + raise util.Abort(_('unknown changeset %s listed') % rulehash[:12]) + return cls(state, node) + + def run(self): + """Runs the action. The default behavior is simply apply the action's + rulectx onto the current parentctx.""" + self.applychange() + self.continuedirty() + return self.continueclean() + + def applychange(self): + """Applies the changes from this action's rulectx onto the current + parentctx, but does not commit them.""" + repo = self.repo + rulectx = repo[self.node] + hg.update(repo, self.state.parentctxnode) + stats = applychanges(repo.ui, repo, rulectx, {}) + if stats and stats[3] > 0: + raise error.InterventionRequired(_('Fix up the change and run ' + 'hg histedit --continue')) + + def continuedirty(self): + """Continues the action when changes have been applied to the working + copy. The default behavior is to commit the dirty changes.""" + repo = self.repo + rulectx = repo[self.node] + + editor = self.commiteditor() + commit = commitfuncfor(repo, rulectx) + + commit(text=rulectx.description(), user=rulectx.user(), + date=rulectx.date(), extra=rulectx.extra(), editor=editor) + + def commiteditor(self): + """The editor to be used to edit the commit message.""" + return False + + def continueclean(self): + """Continues the action when the working copy is clean. The default + behavior is to accept the current commit as the new version of the + rulectx.""" + ctx = self.repo['.'] + if ctx.node() == self.state.parentctxnode: + self.repo.ui.warn(_('%s: empty changeset\n') % + node.short(self.node)) + return ctx, [(self.node, tuple())] + if ctx.node() == self.node: + # Nothing changed + return ctx, [] + return ctx, [(self.node, (ctx.node(),))] + def commitfuncfor(repo, src): """Build a commit function for the replacement of