[PATCH] revert: extract actual revert in its own function

pierre-yves.david at ens-lyon.org pierre-yves.david at ens-lyon.org
Wed Feb 26 21:08:34 CST 2014


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at 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.

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):


More information about the Mercurial-devel mailing list