Patchwork [2,of,4] revert: detect unknown files as the same path as file marked as removed

login
register
mail settings
Submitter Pierre-Yves David
Date Sept. 10, 2014, 1:05 a.m.
Message ID <74eae0c1c351030c7012.1410311139@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/5761/
State Accepted
Headers show

Comments

Pierre-Yves David - Sept. 10, 2014, 1:05 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1409356820 -7200
#      Sat Aug 30 02:00:20 2014 +0200
# Node ID 74eae0c1c351030c701243a3cf0fdee4003130e4
# Parent  5d57e90b2b72e6dc712bc9ec27240485f7208ac5
revert: detect unknown files as the same path as file marked as removed

Such unknown files may need to be backed up. Having them identified beforehand
will help to simplify the backup logic.

We now use different sets with different backup strategy.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2490,10 +2490,28 @@  def revert(ui, repo, ctx, parents, *pats
             # XXX should we check for rename down to target node?
             if src and src not in names and repo.dirstate[src] == 'r':
                 dsremoved.add(src)
                 names[src] = (repo.pathto(src, cwd), True)
 
+        # For files marked as removed, we check if an unknown file is present at
+        # the same path. If a such file exists it may need to be backed up.
+        # Making the distinction at that stage helps having a simpler backup
+        # logic.
+        removunk = set()
+        for abs in removed:
+            target = repo.wjoin(abs)
+            if os.path.lexists(target):
+                removunk.add(abs)
+        removed -= removunk
+
+        dsremovunk = set()
+        for abs in dsremoved:
+            target = repo.wjoin(abs)
+            if os.path.lexists(target):
+                dsremovunk.add(abs)
+        dsremoved -= dsremovunk
+
         ## computation of the action to performs on `names` content.
 
         def removeforget(abs):
             if repo.dirstate[abs] == 'a':
                 return _('forgetting %s\n')
@@ -2526,13 +2544,17 @@  def revert(ui, repo, ctx, parents, *pats
             # Modified compared to target, local change
             (dsmodified,    actions['revert'],   backup),
             # Added since target
             (dsadded,       actions['remove'],   discard),
             # Removed since  target, before working copy parent
-            (removed,       actions['add'],      backup),
+            (removed,       actions['add'],      discard),
+            # Same as `removed` but an unknown file exist at the same path
+            (removunk,      actions['add'],      backup),
             # Removed since targe, marked as such in working copy parent
-            (dsremoved,     actions['undelete'], backup),
+            (dsremoved,     actions['undelete'], discard),
+            # Same as `dsremoved` but an unknown file exist at the same path
+            (dsremovunk,    actions['undelete'], backup),
             ## 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),