[PATCH] update: teach hg to override untracked dir with a tracked file on update

Kostia Balytskyi ikostia at fb.com
Mon Jun 27 16:14:12 UTC 2016


# HG changeset patch
# User Kostia Balytskyi <ikostia at fb.com>
# Date 1467043965 25200
#      Mon Jun 27 09:12:45 2016 -0700
# Node ID b2ede549bfdc4ebbc40b852242c7f1202e0de20b
# Parent  4aa1009ed6f3066874b3937ed77df144fe21efde
update: teach hg to override untracked dir with a tracked file on update

This is a fix to an old problem when Mercurial got confused by an
untracked folder with the same name as one of the files in a commit
hg was trying to update to. It is pretty safe to remove this folder if
it is empty. Backing up an empty folder seems to go agains Mercurial's
"don't track dirs" philosophy.

Let me know if I am wrong about the above assumption please.

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -1076,15 +1076,14 @@ def batchget(repo, mctx, actions):
                 absf = repo.wjoin(f)
                 orig = scmutil.origpath(ui, repo, absf)
                 try:
-                    # TODO Mercurial has always aborted if an untracked
-                    # directory is replaced by a tracked file, or generally
-                    # with file/directory merges. This needs to be sorted out.
                     if repo.wvfs.isfileorlink(f):
                         util.rename(absf, orig)
                 except OSError as e:
                     if e.errno != errno.ENOENT:
                         raise
 
+            if repo.wvfs.isdir(f):
+                repo.wvfs.removedirs(f)
             wwrite(f, fctx(f).data(), flags, backgroundclose=True)
             if i == 100:
                 yield i, f
diff --git a/tests/test-merge1.t b/tests/test-merge1.t
--- a/tests/test-merge1.t
+++ b/tests/test-merge1.t
@@ -24,38 +24,10 @@
   $ hg update 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
 
-Test interrupted updates by exploiting our non-handling of directory collisions
-
-  $ mkdir b
-  $ hg up
-  abort: *: '$TESTTMP/t/b' (glob)
-  [255]
-  $ hg ci
-  abort: last update was interrupted
-  (use 'hg update' to get a consistent checkout)
-  [255]
-  $ hg sum
-  parent: 0:538afb845929 
-   commit #0
-  branch: default
-  commit: (interrupted update)
-  update: 1 new changesets (update)
-  phases: 2 draft
-  $ rmdir b
-  $ hg up
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg sum
-  parent: 1:b8bb4a988f25 tip
-   commit #1
-  branch: default
-  commit: (clean)
-  update: (current)
-  phases: 2 draft
-
 Prepare a basic merge
 
   $ hg up 0
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo This is file c1 > c
   $ hg add c
   $ hg commit -m "commit #2"
diff --git a/tests/test-update-renames.t b/tests/test-update-names.t
rename from tests/test-update-renames.t
rename to tests/test-update-names.t
--- a/tests/test-update-renames.t
+++ b/tests/test-update-names.t
@@ -1,8 +1,9 @@
-Test update logic when there are renames
+Test update logic when there are renames or weird same-name cases between dirs
+and files
 
 Update with local changes across a file rename
 
-  $ hg init
+  $ hg init r1 && cd r1
 
   $ echo a > a
   $ hg add a
@@ -24,3 +25,31 @@ Update with local changes across a file 
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges
   [1]
+
+Test update when local untracked directory exists with the same name as a
+tracked file in a commit we are updating to
+  $ hg init r2 && cd r2
+  $ echo root > root && hg ci -Am root  # rev 0
+  adding root
+  $ echo text > name && hg ci -Am "name is a file"  # rev 1
+  adding name
+  $ hg up 0
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkdir name
+  $ hg up 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Test update when local untracked directory exists with some files in it and has
+the same name a tracked file in a commit we are updating to. In future this
+should be updated to give an friendlier error message, but now we should just
+make sure that this does not erase untracked data
+  $ hg up 0
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkdir name
+  $ echo text > name/file
+  $ hg st
+  ? name/file
+  $ hg up 1
+  abort: Directory not empty: '$TESTTMP/r1/r2/name'
+  [255]
+  $ cd ..


More information about the Mercurial-devel mailing list