Patchwork [2,of,5] histedit: add a new histeditaction class

login
register
mail settings
Submitter Durham Goode
Date April 14, 2015, 6:35 p.m.
Message ID <ab9f5457ac127b75397e.1429036519@dev2000.prn2.facebook.com>
Download mbox | patch
Permalink /patch/8659/
State Accepted
Delegated to: Augie Fackler
Headers show

Comments

Durham Goode - April 14, 2015, 6:35 p.m.
# HG changeset patch
# User Durham Goode <durham@fb.com>
# Date 1428172493 25200
#      Sat Apr 04 11:34:53 2015 -0700
# Node ID ab9f5457ac127b75397e2f3ff23ed484c8800476
# Parent  7560f2555bcef1a31138106b02631aab7112567f
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.

Patch

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -237,6 +237,72 @@  class histeditstate(object):
     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 <src>