diff mercurial/dirstate.py @ 2954:51ba31494c69

merge.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Fri, 18 Aug 2006 21:04:10 -0700
parents 3d5547845158
children 882e703eaa94
line wrap: on
line diff
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -10,7 +10,7 @@ of the GNU General Public License, incor
 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 @@ class dirstate(object):
         self.ui = ui
         self.map = None
         self.pl = None
+        self.dirs = None
         self.copies = {}
         self.ignorefunc = None
         self.blockignore = False
@@ -197,6 +198,38 @@ class dirstate(object):
     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 @@ class dirstate(object):
         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 @@ class dirstate(object):
         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 @@ class dirstate(object):
     def clear(self):
         self.map = {}
         self.copies = {}
+        self.dirs = None
         self.markdirty()
 
     def rebuild(self, parent, files):