[PATCH 4 of 6] scmutil: check collision between added file and directory part of tracked ones
FUJIWARA Katsunori
foozy at lares.dti.ne.jp
Thu Nov 14 10:08:00 CST 2013
# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1384438902 -32400
# Thu Nov 14 23:21:42 2013 +0900
# Node ID 74abacdb51c2bafb92077c85b9a9e917ddeb82a9
# Parent 284ca308c2eb1db65021f94c1c9c0a93b5f84650
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.
If "self._exact()" is False, "lower in self._lowereddirs" should be
examined again, because removed files may cause that it is True: in
this case, "self._lowereddirs" is already re-built in "self._exact()".
If no case-folding collision occurs, this delay avoids cost to
eliminate removed files from "self._loweredfiles" and
"self._lowereddirs".
In fact, "lower in self._lowereddirs" is enough for collision check
itself, because it means case-folding collision between file and
directory.
But adding file in NOT "actual 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.
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -90,6 +90,7 @@
self._abort = abort
allfiles = '\0'.join(dirstate._map)
self._loweredfiles = set(encoding.lower(allfiles).split('\0'))
+ self._lowereddirs = dirs(self._loweredfiles)
self._existingonly = False
self._dirstate = dirstate
# The purpose of _newfiles is so that we don't complain about
@@ -101,11 +102,19 @@
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
+ self._checkdirs(f, fl)):
self._oncollision(f)
self._loweredfiles.add(fl)
+ self._lowereddirs.addpath(fl)
self._newfiles.add(f)
+ def _checkdirs(self, actual, lower):
+ if lower in self._lowereddirs:
+ if self._exact() or lower in self._lowereddirs:
+ return actual not in self._dirstate.dirs()
+ return False
+
def _oncollision(self, f):
msg = _('possible case-folding collision for %s') % f
if self._abort:
@@ -123,6 +132,7 @@
existing.append(f)
allfiles = '\0'.join(existing)
self._loweredfiles = set(encoding.lower(allfiles).split('\0'))
+ self._lowereddirs = dirs(self._loweredfiles)
self._existingonly = True
return False
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
More information about the Mercurial-devel
mailing list