Patchwork revert: extract actual revert in its own function

login
register
mail settings
Submitter Pierre-Yves David
Date Feb. 27, 2014, 3:08 a.m.
Message ID <8710b2b0b16bbd0f2f20.1393470514@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/3782/
State Accepted
Commit d4893e64f30031d3ac7c3222776d5ccde43893a8
Headers show

Comments

Pierre-Yves David - Feb. 27, 2014, 3:08 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1393469787 28800
#      Wed Feb 26 18:56:27 2014 -0800
# Node ID 8710b2b0b16bbd0f2f200c8b64e4a3537dc99507
# Parent  0ad353831461516132f57ccda8e8e0515213ec60
revert: extract actual revert in its own function

With this small refactoring, the computation of the action to perform and the
actual change to the disk happen in different function. This allows extension to
wrap the later in case of need. The initial motivation is the `remotefilelog`
extension that need to prefetch all the file content to be checked out.
Matt Mackall - Feb. 27, 2014, 9:58 p.m.
On Wed, 2014-02-26 at 19:08 -0800, pierre-yves.david@ens-lyon.org wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@fb.com>
> # Date 1393469787 28800
> #      Wed Feb 26 18:56:27 2014 -0800
> # Node ID 8710b2b0b16bbd0f2f200c8b64e4a3537dc99507
> # Parent  0ad353831461516132f57ccda8e8e0515213ec60
> revert: extract actual revert in its own function

Queued for default, thanks.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2193,66 +2193,77 @@  def revert(ui, repo, ctx, parents, *pats
                     if (pmf[abs] != mfentry or
                         pmf.flags(abs) != mf.flags(abs)):
                         handle(revert, False)
                 else:
                     handle(remove, False)
-
         if not opts.get('dry_run'):
-            def checkout(f):
-                fc = ctx[f]
-                repo.wwrite(f, fc.data(), fc.flags())
-
-            audit_path = pathutil.pathauditor(repo.root)
-            for f in remove[0]:
-                if repo.dirstate[f] == 'a':
-                    repo.dirstate.drop(f)
-                    continue
-                audit_path(f)
-                try:
-                    util.unlinkpath(repo.wjoin(f))
-                except OSError:
-                    pass
-                repo.dirstate.remove(f)
-
-            normal = None
-            if node == parent:
-                # We're reverting to our parent. If possible, we'd like status
-                # to report the file as clean. We have to use normallookup for
-                # merges to avoid losing information about merged/dirty files.
-                if p2 != nullid:
-                    normal = repo.dirstate.normallookup
-                else:
-                    normal = repo.dirstate.normal
-            for f in revert[0]:
-                checkout(f)
-                if normal:
-                    normal(f)
-
-            for f in add[0]:
-                checkout(f)
-                repo.dirstate.add(f)
-
-            normal = repo.dirstate.normallookup
-            if node == parent and p2 == nullid:
-                normal = repo.dirstate.normal
-            for f in undelete[0]:
-                checkout(f)
-                normal(f)
-
-            copied = copies.pathcopies(repo[parent], ctx)
-
-            for f in add[0] + undelete[0] + revert[0]:
-                if f in copied:
-                    repo.dirstate.copy(copied[f], f)
+            _performrevert(repo, parents, ctx, revert, add, remove, undelete)
 
             if targetsubs:
                 # Revert the subrepos on the revert list
                 for sub in targetsubs:
                     ctx.sub(sub).revert(ui, ctx.substate[sub], *pats, **opts)
     finally:
         wlock.release()
 
+def _performrevert(repo, parents, ctx, revert, add, remove, undelete):
+    """function that actually perform all the action computed for revert
+
+    This is an independent function to let extension to plug in and react to
+    the imminent revert.
+
+    Make sure you have the working directory locked when caling this function.
+    """
+    parent, p2 = parents
+    node = ctx.node()
+    def checkout(f):
+        fc = ctx[f]
+        repo.wwrite(f, fc.data(), fc.flags())
+
+    audit_path = pathutil.pathauditor(repo.root)
+    for f in remove[0]:
+        if repo.dirstate[f] == 'a':
+            repo.dirstate.drop(f)
+            continue
+        audit_path(f)
+        try:
+            util.unlinkpath(repo.wjoin(f))
+        except OSError:
+            pass
+        repo.dirstate.remove(f)
+
+    normal = None
+    if node == parent:
+        # We're reverting to our parent. If possible, we'd like status
+        # to report the file as clean. We have to use normallookup for
+        # merges to avoid losing information about merged/dirty files.
+        if p2 != nullid:
+            normal = repo.dirstate.normallookup
+        else:
+            normal = repo.dirstate.normal
+    for f in revert[0]:
+        checkout(f)
+        if normal:
+            normal(f)
+
+    for f in add[0]:
+        checkout(f)
+        repo.dirstate.add(f)
+
+    normal = repo.dirstate.normallookup
+    if node == parent and p2 == nullid:
+        normal = repo.dirstate.normal
+    for f in undelete[0]:
+        checkout(f)
+        normal(f)
+
+    copied = copies.pathcopies(repo[parent], ctx)
+
+    for f in add[0] + undelete[0] + revert[0]:
+        if f in copied:
+            repo.dirstate.copy(copied[f], f)
+
 def command(table):
     '''returns a function object bound to table which can be used as
     a decorator for populating table as a command table'''
 
     def cmd(name, options=(), synopsis=None):