merge: abort on file/directory case folding collisions (issue4892)
authorMads Kiilerich <madski@unity3d.com>
Tue, 13 Oct 2015 00:16:25 +0200
changeset 26661 2b955fec91e0
parent 26660 7e1baad90121
child 26662 d215def59c3b
merge: abort on file/directory case folding collisions (issue4892) File/directory case folding collisions cannot be represented on case folding systems and have to fail. To detect this and abort early, utilize that for file/directory collisions, a sorted list of case folded manifest names will have the colliding directory right after the file. (This could perhaps be optimized, but this way of doing it also has directory/directory case folding in mind ... which however not is handled yet.)
mercurial/merge.py
tests/test-casecollision-merge.t
--- a/mercurial/merge.py	Tue Oct 13 00:16:25 2015 +0200
+++ b/mercurial/merge.py	Tue Oct 13 00:16:25 2015 +0200
@@ -478,6 +478,17 @@
                              % (f, foldmap[fold]))
         foldmap[fold] = f
 
+    # check case-folding of directories
+    foldprefix = unfoldprefix = lastfull = ''
+    for fold, f in sorted(foldmap.items()):
+        if fold.startswith(foldprefix) and not f.startswith(unfoldprefix):
+            # the folded prefix matches but actual casing is different
+            raise error.Abort(_("case-folding collision between "
+                                "%s and directory of %s") % (lastfull, f))
+        foldprefix = fold + '/'
+        unfoldprefix = f + '/'
+        lastfull = f
+
 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
                   acceptremote, followcopies):
     """
--- a/tests/test-casecollision-merge.t	Tue Oct 13 00:16:25 2015 +0200
+++ b/tests/test-casecollision-merge.t	Tue Oct 13 00:16:25 2015 +0200
@@ -212,7 +212,7 @@
   $ hg ci -Aqm1
 
   $ hg merge 0
-  abort: Not a directory: '$TESTTMP/directory-casing/aA/a'
+  abort: case-folding collision between Aa and directory of aA/a
   [255]
 (note: no collision between 0 and 00 or 000/f)