issue 1286: dirstat regression on case folding systems
authorPetr Kodl <petrkodl@gmail.com>
Tue, 30 Sep 2008 17:23:08 -0400
changeset 7068 57377fa7eda2
parent 7067 40d105a12cac
child 7069 852f39691a0a
issue 1286: dirstat regression on case folding systems This patch fixes regression reported in 1286 that causes util.fspath to be called for every file not in current manifest - including ignored files. The regression is quite severe - the time for simple hg st goes from 5s to 1m38s on one of my source trees - which basically renders mercurial useless.
mercurial/dirstate.py
--- a/mercurial/dirstate.py	Wed Oct 08 16:22:10 2008 -0500
+++ b/mercurial/dirstate.py	Tue Sep 30 17:23:08 2008 -0400
@@ -98,7 +98,7 @@
             if self._checkcase:
                 self.normalize = self._normalize
             else:
-                self.normalize = lambda x: x
+                self.normalize = lambda x, y=False: x
             return self.normalize
         else:
             raise AttributeError(name)
@@ -350,13 +350,16 @@
         except KeyError:
             self._ui.warn(_("not in dirstate: %s\n") % f)
 
-    def _normalize(self, path):
+    def _normalize(self, path, knownpath=False):
         norm_path = os.path.normcase(os.path.normpath(path))
-        if norm_path not in self._foldmap:
-            if not os.path.exists(os.path.join(self._root, path)):
-                return path
-            self._foldmap[norm_path] = util.fspath(path, self._root)
-        return self._foldmap[norm_path]
+        fold_path = self._foldmap.get(norm_path, None)
+        if fold_path is None:
+            if knownpath or not os.path.exists(os.path.join(self._root, path)):
+                fold_path = path
+            else:
+                fold_path = self._foldmap.setdefault(norm_path,
+                                util.fspath(path, self._root))
+        return fold_path
 
     def clear(self):
         self._map = {}
@@ -515,7 +518,7 @@
             else:
                 entries = listdir(join(nd), stat=True, skip ='.hg')
             for f, kind, st in entries:
-                nf = normalize(nd and (nd + "/" + f) or f)
+                nf = normalize(nd and (nd + "/" + f) or f, True)
                 if nf not in results:
                     if kind == dirkind:
                         if not ignore(nf):