[PATCH 1 of 6 STABLE V3] pathauditor: switch normcase logic according to case sensitivity of filesystem

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Mon Dec 12 07:25:37 CST 2011


# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1323677419 -32400
# Branch stable
# Node ID 3145a0ba21aff7b1d9f9c49fcff8eb286c1c75b6
# Parent  09b200396384b5e3b184c551c5ce348faa995771
pathauditor: switch normcase logic according to case sensitivity of filesystem

this patch applies 'util.normcase()' to audit path only on case
insensitive filesystem.

both plain and normcase()-ed pathes are used to preserve case in abort
messages.

changing to util.checkcase() prevents case-less name from misleading
into case insensitivity for safety, even though such names should not
be used.

diff -r 09b200396384 -r 3145a0ba21af mercurial/scmutil.py
--- a/mercurial/scmutil.py	Mon Dec 05 17:09:11 2011 -0600
+++ b/mercurial/scmutil.py	Mon Dec 12 17:10:19 2011 +0900
@@ -76,18 +76,21 @@
         self.auditeddir = set()
         self.root = root
         self.callback = callback
+        self.normcase = ((not os.path.lexists(root) or util.checkcase(root))
+                         and (lambda x: x)
+                         or util.normcase)
 
     def __call__(self, path):
         '''Check the relative path.
         path may contain a pattern (e.g. foodir/**.txt)'''
 
-        if path in self.audited:
+        normpath = self.normcase(path)
+        if normpath in self.audited:
             return
         # AIX ignores "/" at end of path, others raise EISDIR.
         if util.endswithsep(path):
             raise util.Abort(_("path ends in directory separator: %s") % path)
-        normpath = os.path.normcase(path)
-        parts = util.splitpath(normpath)
+        parts = util.splitpath(path)
         if (os.path.splitdrive(path)[0]
             or parts[0].lower() in ('.hg', '.hg.', '')
             or os.pardir in parts):
@@ -101,11 +104,16 @@
                     raise util.Abort(_('path %r is inside nested repo %r')
                                      % (path, base))
 
+        normparts = util.splitpath(normpath)
+        assert len(parts) == len(normparts)
+
         parts.pop()
+        normparts.pop()
         prefixes = []
         while parts:
             prefix = os.sep.join(parts)
-            if prefix in self.auditeddir:
+            normprefix = os.sep.join(normparts)
+            if normprefix in self.auditeddir:
                 break
             curpath = os.path.join(self.root, prefix)
             try:
@@ -125,10 +133,11 @@
                     if not self.callback or not self.callback(curpath):
                         raise util.Abort(_('path %r is inside nested repo %r') %
                                          (path, prefix))
-            prefixes.append(prefix)
+            prefixes.append(normprefix)
             parts.pop()
+            normparts.pop()
 
-        self.audited.add(path)
+        self.audited.add(normpath)
         # only add prefixes to the cache after checking everything: we don't
         # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
         self.auditeddir.update(prefixes)
diff -r 09b200396384 -r 3145a0ba21af mercurial/util.py
--- a/mercurial/util.py	Mon Dec 05 17:09:11 2011 -0600
+++ b/mercurial/util.py	Mon Dec 12 17:10:19 2011 +0900
@@ -595,9 +595,12 @@
     """
     s1 = os.stat(path)
     d, b = os.path.split(path)
-    p2 = os.path.join(d, b.upper())
-    if path == p2:
-        p2 = os.path.join(d, b.lower())
+    b2 = b.upper()
+    if b == b2:
+        b2 = b.lower()
+        if b == b2:
+            return True # no evidence against case sensitivity
+    p2 = os.path.join(d, b2)
     try:
         s2 = os.stat(p2)
         if s2 == s1:


More information about the Mercurial-devel mailing list