mercurial/dirstate.py
branchstable
changeset 16542 e596a631210e
parent 16509 eab9119c5dee
child 16551 ebf6d38c9063
--- a/mercurial/dirstate.py	Sat Apr 28 02:00:04 2012 +0200
+++ b/mercurial/dirstate.py	Sat Apr 28 20:29:21 2012 +0200
@@ -408,32 +408,48 @@
             self._droppath(f)
             del self._map[f]
 
-    def _normalize(self, path, isknown):
+    def _normalize(self, path, isknown, ignoremissing=False, exists=None):
         normed = util.normcase(path)
         folded = self._foldmap.get(normed, None)
         if folded is None:
-            if isknown or not os.path.lexists(os.path.join(self._root, path)):
+            if isknown:
                 folded = path
             else:
-                # recursively normalize leading directory components
-                # against dirstate
-                if '/' in normed:
-                    d, f = normed.rsplit('/', 1)
-                    d = self._normalize(d, isknown)
-                    r = self._root + "/" + d
-                    folded = d + "/" + util.fspath(f, r)
+                if exists is None:
+                    exists = os.path.lexists(os.path.join(self._root, path))
+                if not exists:
+                    # Maybe a path component exists
+                    if not ignoremissing and '/' in path:
+                        d, f = path.rsplit('/', 1)
+                        d = self._normalize(d, isknown, ignoremissing, None)
+                        folded = d + "/" + f
+                    else:
+                        # No path components, preserve original case
+                        folded = path
                 else:
-                    folded = util.fspath(normed, self._root)
-                self._foldmap[normed] = folded
+                    # recursively normalize leading directory components
+                    # against dirstate
+                    if '/' in normed:
+                        d, f = normed.rsplit('/', 1)
+                        d = self._normalize(d, isknown, ignoremissing, True)
+                        r = self._root + "/" + d
+                        folded = d + "/" + util.fspath(f, r)
+                    else:
+                        folded = util.fspath(normed, self._root)
+                    self._foldmap[normed] = folded
 
         return folded
 
-    def normalize(self, path, isknown=False):
+    def normalize(self, path, isknown=False, ignoremissing=False):
         '''
         normalize the case of a pathname when on a casefolding filesystem
 
         isknown specifies whether the filename came from walking the
-        disk, to avoid extra filesystem access
+        disk, to avoid extra filesystem access.
+
+        If ignoremissing is True, missing path are returned
+        unchanged. Otherwise, we try harder to normalize possibly
+        existing path components.
 
         The normalized case is determined based on the following precedence:
 
@@ -443,7 +459,7 @@
         '''
 
         if self._checkcase:
-            return self._normalize(path, isknown)
+            return self._normalize(path, isknown, ignoremissing)
         return path
 
     def clear(self):
@@ -575,7 +591,7 @@
             normalize = self._normalize
             skipstep3 = False
         else:
-            normalize = lambda x, y: x
+            normalize = lambda x, y, z: x
 
         files = sorted(match.files())
         subrepos.sort()
@@ -596,7 +612,7 @@
 
         # step 1: find all explicit files
         for ff in files:
-            nf = normalize(normpath(ff), False)
+            nf = normalize(normpath(ff), False, True)
             if nf in results:
                 continue
 
@@ -646,7 +662,7 @@
                     continue
                 raise
             for f, kind, st in entries:
-                nf = normalize(nd and (nd + "/" + f) or f, True)
+                nf = normalize(nd and (nd + "/" + f) or f, True, True)
                 if nf not in results:
                     if kind == dirkind:
                         if not ignore(nf):