[PATCH 2 of 4 V2] revert: distinct between "check" and "backup" strategy

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Sep 30 13:05:38 CDT 2014


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1409358624 -7200
#      Sat Aug 30 02:30:24 2014 +0200
# Node ID 9d3552b955c8cdffcb7e4d0bf88983abc2fede16
# Parent  5ddd515bd5209e36ccc0cc40d9e8436253bc611b
revert: distinct between "check" and "backup" strategy

"check" behave as backup did before. We check if the current file differs
from destination and we create a backup if it does. This is used for untracked
file that will be overwritten by formerly deleted file. We have to do the manual
check since no status output can provides the content comparison.

"backup" is now doing unconditional backup. This can be used for file seen as
modified compared to both the target and the working directory. In such case we
know that the file differs from target without actually comparing any content.

This new "backup" strategy will be especially useful in the case of file added
between the target and the working directory -parent- with additional modifications
in the working directory -itself-. In that case we know we need to backup it, but we
cannot run the content check as the files does not exists in target.

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2619,13 +2619,14 @@ def revert(ui, repo, ctx, parents, *pats
 
         # "constant" that convey the backup strategy.
         # All set to `discard` if `no-backup` is set do avoid checking
         # no_backup lower in the code.
         backup = 2  # unconditionnally do backup
+        check = 1   # check if existing file differ from target
         discard = 0 # never do backup
         if opts.get('no_backup'):
-            backup = discard
+            backup = check = discard
 
         disptable = (
             # dispatch table:
             #   file state
             #   action
@@ -2645,15 +2646,15 @@ def revert(ui, repo, ctx, parents, *pats
             # Added since target but file is missing in working directory
             (deladded,      actions['drop'],   discard),
             # Removed since  target, before working copy parent
             (removed,       actions['add'],      discard),
             # Same as `removed` but an unknown file exists at the same path
-            (removunk,      actions['add'],      backup),
+            (removunk,      actions['add'],      check),
             # Removed since targe, marked as such in working copy parent
             (dsremoved,     actions['undelete'], discard),
             # Same as `dsremoved` but an unknown file exists at the same path
-            (dsremovunk,    actions['undelete'], backup),
+            (dsremovunk,    actions['undelete'], check),
             ## the following sets does not result in any file changes
             # File with no modification
             (clean,         actions['noop'],     discard),
             # Existing file, not tracked anywhere
             (unknown,       actions['unknown'],  discard),
@@ -2672,16 +2673,17 @@ def revert(ui, repo, ctx, parents, *pats
             for table, (xlist, msg), dobackup in disptable:
                 if abs not in table:
                     continue
                 if xlist is not None:
                     xlist.append(abs)
-                    if (dobackup and wctx[abs].cmp(ctx[abs])):
-                        bakname = "%s.orig" % rel
-                        ui.note(_('saving current version of %s as %s\n') %
-                                (rel, bakname))
-                        if not opts.get('dry_run'):
-                            util.rename(target, bakname)
+                    if dobackup and (backup <= dobackup
+                                     or wctx[abs].cmp(ctx[abs])):
+                            bakname = "%s.orig" % rel
+                            ui.note(_('saving current version of %s as %s\n') %
+                                    (rel, bakname))
+                            if not opts.get('dry_run'):
+                                util.rename(target, bakname)
                     if ui.verbose or not exact:
                         if not isinstance(msg, basestring):
                             msg = msg(abs)
                         ui.status(msg % rel)
                 elif exact:


More information about the Mercurial-devel mailing list