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