# HG changeset patch # User Vadim Gelfer # Date 1155960250 25200 # Node ID 51ba31494c69820258e34b8239cddcd60656b367 # Parent 6ba3409f9725c663fa12468ceb9b89b2af5908b6# Parent 3d5547845158a6a017dbf7a6775ee122b84320eb merge. diff -r 6ba3409f9725 -r 51ba31494c69 mercurial/dirstate.py --- a/mercurial/dirstate.py Fri Aug 18 17:02:38 2006 -0700 +++ b/mercurial/dirstate.py Fri Aug 18 21:04:10 2006 -0700 @@ -10,7 +10,7 @@ from node import * from i18n import gettext as _ from demandload import * -demandload(globals(), "struct os time bisect stat util re errno") +demandload(globals(), "struct os time bisect stat strutil util re errno") class dirstate(object): format = ">cllll" @@ -22,6 +22,7 @@ self.ui = ui self.map = None self.pl = None + self.dirs = None self.copies = {} self.ignorefunc = None self.blockignore = False @@ -197,6 +198,38 @@ def copied(self, file): return self.copies.get(file, None) + def initdirs(self): + if self.dirs is None: + self.dirs = {} + for f in self.map: + self.updatedirs(f, 1) + + def updatedirs(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 + + def checkshadows(self, files): + def prefixes(f): + for c in strutil.rfindall(f, '/'): + yield f[:c] + self.lazyread() + self.initdirs() + seendirs = {} + for f in files: + if self.dirs.get(f): + raise util.Abort(_('directory named %r already in dirstate') % + f) + for d in prefixes(f): + if d in seendirs: + break + if d in self.map: + raise util.Abort(_('file named %r already in dirstate') % + d) + seendirs[d] = True + def update(self, files, state, **kw): ''' current states: n normal @@ -207,10 +240,16 @@ if not files: return self.lazyread() self.markdirty() + if state == "a": + self.initdirs() + self.checkshadows(files) for f in files: if state == "r": self.map[f] = ('r', 0, 0, 0) + self.updatedirs(f, -1) else: + if state == "a": + self.updatedirs(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) @@ -222,9 +261,11 @@ if not files: return self.lazyread() self.markdirty() + self.initdirs() for f in files: try: del self.map[f] + self.updatedirs(f, -1) except KeyError: self.ui.warn(_("not in dirstate: %s!\n") % f) pass @@ -232,6 +273,7 @@ def clear(self): self.map = {} self.copies = {} + self.dirs = None self.markdirty() def rebuild(self, parent, files): diff -r 6ba3409f9725 -r 51ba31494c69 mercurial/strutil.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/strutil.py Fri Aug 18 21:04:10 2006 -0700 @@ -0,0 +1,34 @@ +# strutil.py - string utilities for Mercurial +# +# Copyright 2006 Vadim Gelfer +# +# This software may be used and distributed according to the terms +# of the GNU General Public License, incorporated herein by reference. + +def findall(haystack, needle, start=0, end=None): + if end is None: + end = len(haystack) + if end < 0: + end += len(haystack) + if start < 0: + start += len(haystack) + while start < end: + c = haystack.find(needle, start, end) + if c == -1: + break + yield c + start = c + 1 + +def rfindall(haystack, needle, start=0, end=None): + if end is None: + end = len(haystack) + if end < 0: + end += len(haystack) + if start < 0: + start += len(haystack) + while end >= 0: + c = haystack.rfind(needle, start, end) + if c == -1: + break + yield c + end = c - 1 diff -r 6ba3409f9725 -r 51ba31494c69 mercurial/util.py --- a/mercurial/util.py Fri Aug 18 17:02:38 2006 -0700 +++ b/mercurial/util.py Fri Aug 18 21:04:10 2006 -0700 @@ -995,4 +995,3 @@ if path.startswith('//'): path = path[2:] return path - diff -r 6ba3409f9725 -r 51ba31494c69 tests/test-issue322 --- a/tests/test-issue322 Fri Aug 18 17:02:38 2006 -0700 +++ b/tests/test-issue322 Fri Aug 18 21:04:10 2006 -0700 @@ -14,15 +14,7 @@ echo % should fail - would corrupt dirstate hg add a/a -echo % should fail - if add succeeded, would corrupt manifest -hg commit -mb - -echo % should fail if commit succeeded - manifest is corrupt -hg verify - cd .. -echo % should succeed, but manifest is corrupt -hg --debug --traceback clone a b echo % directory replaced with file @@ -38,8 +30,20 @@ echo % should fail - would corrupt dirstate hg add a -echo % should fail - if add succeeded, would corrupt manifest -hg commit -mb a +cd .. + +echo % directory replaced with file -echo % should fail if commit succeeded - manifest is corrupt -hg verify +hg init d +cd d +mkdir b +mkdir b/c +echo a > b/c/d +hg commit -Ama +rm -rf b +echo a > b + +echo % should fail - would corrupt dirstate +hg add b + +exit 0 diff -r 6ba3409f9725 -r 51ba31494c69 tests/test-issue322.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-issue322.out Fri Aug 18 21:04:10 2006 -0700 @@ -0,0 +1,12 @@ +% file replaced with directory +adding a +% should fail - would corrupt dirstate +abort: file named 'a' already in dirstate +% directory replaced with file +adding a/a +% should fail - would corrupt dirstate +abort: directory named 'a' already in dirstate +% directory replaced with file +adding b/c/d +% should fail - would corrupt dirstate +abort: directory named 'b' already in dirstate