[PATCH] Check case-folding clashes during addremove
Andrei Vermel
andrei.vermel at gmail.com
Tue May 15 18:57:28 UTC 2007
----- Original Message -----
From: "Alexis S. L. Carvalho" <alexis at cecm.usp.br>
To: "Andrei Vermel" <andrei.vermel at gmail.com>
Cc: "Matt Mackall" <mpm at selenic.com>; "Mercurial Devel" <mercurial-devel at selenic.com>
Sent: Monday, April 16, 2007 3:08 AM
Subject: Re: [PATCH] Check case-folding clashes during addremove
> Instead of populating the foldmap every time we read the dirstate file,
> it'd be better to do it only when we're going to use it, just like the
> initdirs/checkinterfering calls in dirstate.update below. (Maybe it
> even makes sense to rename initdirs/updatedirs -> initchecks/updatechecks,
> add the foldmap management to these functions and make checkinterfering
> call check_add_case_clashes)
Yes, this makes sense. Modified patch is below and attached.
Regards,
Andrei
# HG changeset patch
# User Andrei Vermel <avermel at mail.ru>
# Date 1179088540 -14400
# Node ID 7e9678d540dc735fbbdfa90b35ff027b4d201e04
# Parent ba22e867cb23fb11f83c37705743e050afd66a6a
Check case-folding clashes during addremove
diff -r ba22e867cb23 -r 7e9678d540dc mercurial/dirstate.py
--- a/mercurial/dirstate.py Mon May 07 21:44:11 2007 +0900
+++ b/mercurial/dirstate.py Mon May 14 00:35:40 2007 +0400
@@ -24,6 +24,7 @@ class dirstate(object):
self.fp = None
self.pl = None
self.dirs = None
+ self.foldmap = None
self.copymap = {}
self.ignorefunc = None
self._branch = None
@@ -252,25 +253,29 @@ class dirstate(object):
def copies(self):
return self.copymap
- def initdirs(self):
+ def initchecks(self):
if self.dirs is None:
self.dirs = {}
+ self.foldmap = {}
for f in self.map:
- self.updatedirs(f, 1)
-
- def updatedirs(self, path, delta):
+ self.updatechecks(f, 1)
+
+ def updatechecks(self, path, delta):
if self.dirs is not None:
for c in strutil.findall(path, '/'):
pc = path[:c]
self.dirs.setdefault(pc, 0)
self.dirs[pc] += delta
+ fl = path.lower()
+ self.foldmap.setdefault(fl, 0)
+ self.foldmap[fl] += delta
def checkinterfering(self, files):
def prefixes(f):
for c in strutil.rfindall(f, '/'):
yield f[:c]
self.lazyread()
- self.initdirs()
+ self.initchecks()
seendirs = {}
for f in files:
# shadows
@@ -287,6 +292,7 @@ class dirstate(object):
# disallowed
if '\r' in f or '\n' in f:
raise util.Abort(_("'\\n' and '\\r' disallowed in filenames"))
+ self.check_add_case_clashes(files)
def update(self, files, state, **kw):
''' current states:
@@ -299,15 +305,15 @@ class dirstate(object):
self.lazyread()
self.markdirty()
if state == "a":
- self.initdirs()
+ self.initchecks()
self.checkinterfering(files)
for f in files:
if state == "r":
self.map[f] = ('r', 0, 0, 0)
- self.updatedirs(f, -1)
+ self.updatechecks(f, -1)
else:
if state == "a":
- self.updatedirs(f, 1)
+ self.updatechecks(f, 1)
s = os.lstat(self.wjoin(f))
st_size = kw.get('st_size', s.st_size)
st_mtime = kw.get('st_mtime', s.st_mtime)
@@ -319,11 +325,11 @@ class dirstate(object):
if not files: return
self.lazyread()
self.markdirty()
- self.initdirs()
+ self.initchecks()
for f in files:
try:
del self.map[f]
- self.updatedirs(f, -1)
+ self.updatechecks(f, -1)
except KeyError:
self.ui.warn(_("not in dirstate: %s!\n") % f)
pass
@@ -332,6 +338,7 @@ class dirstate(object):
self.map = {}
self.copymap = {}
self.dirs = None
+ self.foldmap = None
self.markdirty()
def rebuild(self, parent, files):
@@ -588,3 +595,37 @@ class dirstate(object):
return (lookup, modified, added, removed, deleted, unknown, ignored,
clean)
+
+ def check_add_case_clashes(self, add_files):
+ self.lazyread()
+ foldmap = self.foldmap
+ fold_clash = None
+ for fn in add_files:
+ fold=fn.lower()
+ if fold in foldmap:
+ nmb = foldmap[fold]
+ if nmb == 0:
+ continue
+ if fn in self.map: # add existing file is valid,
+ continue # e.g. qrefresh does it
+
+ coll=self.report_case_collisions(fn)
+
+
+ def report_case_collisions(self, file):
+ fold = file.lower()
+ clashes=[]
+ for fn in self.map.iterkeys():
+ fl = fn.lower()
+ if fl == fold and fn != file and self.map[fn][0] != 'r':
+ clashes.append(fn)
+
+ if clashes != []:
+ self.ui.warn(_('\nname case fold clashes found!\n'))
+ self.ui.warn(_(' was %s') % clashes[0])
+ for fn in clashes[1:]:
+ self.ui.warn(_(',\n %s') % fn)
+ self.ui.warn(_(', now %s\n') % file)
+
+ if not util.checkfolding(self.root):
+ raise util.Abort(_('add aborted due to case folding clashes'))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: name_clashes.diff
Type: application/octet-stream
Size: 4733 bytes
Desc: not available
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-devel/attachments/20070515/8650134d/attachment-0002.obj>
More information about the Mercurial-devel
mailing list