[PATCH 1 of 3] issue 1286: dirstat regression on case folding systems

Petr Kodl petrkodl at gmail.com
Tue Sep 30 13:54:18 CDT 2008


# HG changeset patch
# User Petr Kodl <petrkodl at gmail.com>
# Date 1222799587 14400
# Node ID 50c9963d5a5ed98bf1046d0ca897d00b0cedc4b2
# Parent  9e6d6568bf7a21f900273de027d8975a4e0cecae
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.

diff -r 9e6d6568bf7a -r 50c9963d5a5e mercurial/dirstate.py
--- a/mercurial/dirstate.py	Mon Sep 29 12:12:53 2008 +0200
+++ b/mercurial/dirstate.py	Tue Sep 30 14:33:07 2008 -0400
@@ -98,7 +98,7 @@
             if self._checkcase:
                 self.normalize = self._normalize
             else:
-                self.normalize = lambda x: x
+                self.normalize = lambda x, y=None: x
             return self.normalize
         else:
             raise AttributeError(name)
@@ -349,15 +349,16 @@
             del self._map[f]
         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 = {}
         if "_dirs" in self.__dict__:
@@ -515,7 +516,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):


More information about the Mercurial-devel mailing list