Patchwork [3,of,5] scmutil: check collision between added file and directory part of tracked ones

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Nov. 11, 2013, 3:15 p.m.
Message ID <69fed456e3a20657acad.1384182958@juju>
Download mbox | patch
Permalink /patch/2906/
State Superseded
Headers show

Comments

Katsunori FUJIWARA - Nov. 11, 2013, 3:15 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1384182518 -32400
#      Tue Nov 12 00:08:38 2013 +0900
# Node ID 69fed456e3a20657acad10eae294951fc64d04fa
# Parent  5cede77133f0b1311892898965dfd52d12056d9b
scmutil: check collision between added file and directory part of tracked ones

Before this patch, "hg add" doesn't show any warning messages, when
newly added file causes case-folding collision against directory part
of already tracked ones.

Such adding causes failure of "hg update" on icasefs system.

This patch checks case-folding collision between newly added file and
directory part of already tracked ones.

In fact, "fl in self._lowereddirs" is enough for collision check
itself, because it means case-folding collision between file and
directory.

But adding file in NOT "f not in self._dirstate.dirs()" case should be
aborted in "dirstate._addpath()" (see also issues #660 and #332).

To prevent regression, this patch tests also that collision between
newly added file and directory part of already removed one is ignored.

Patch

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -96,17 +96,21 @@ 
         # same filename twice.
         self._newfiles = set()
 
+        self._lowereddirs = dirs(self._loweredfiles)
+
     def __call__(self, f):
         if f in self._newfiles:
             return
         fl = encoding.lower(f)
-        if fl in self._loweredfiles and f not in self._dirstate:
+        if (fl in self._loweredfiles and f not in self._dirstate or
+            fl in self._lowereddirs and f not in self._dirstate.dirs()):
             msg = _('possible case-folding collision for %s') % f
             if self._abort:
                 raise util.Abort(msg)
             self._ui.warn(_("warning: %s\n") % msg)
         self._loweredfiles.add(fl)
         self._newfiles.add(f)
+        self._lowereddirs.addpath(fl)
 
 class pathauditor(object):
     '''ensure that a filesystem path contains no banned components.
diff --git a/tests/test-casecollision.t b/tests/test-casecollision.t
--- a/tests/test-casecollision.t
+++ b/tests/test-casecollision.t
@@ -63,6 +63,20 @@ 
   $ hg add H/s
   warning: possible case-folding collision for H/s
 
+  $ mkdir -p I/I1
+  $ touch I/I1/x I/i1
+  $ hg add I/I1/x I/i1
+  warning: possible case-folding collision for I/i1
+  $ mkdir -p I/I2
+  $ touch I/I2/x
+  $ hg add I/I2/x
+
+  $ hg commit -m '#0'
+
+  $ hg remove I/I2/x
+  $ touch I/i2
+  $ hg add I/i2
+
 case changing rename must not warn or abort
 
   $ echo c > c