dirstate: don't require exact case when adding dirs on icasefs (issue4578) stable
authorMatt Harbison <matt_harbison@yahoo.com>
Tue, 31 Mar 2015 11:11:39 -0400
branchstable
changeset 24537 2bb13f2b778c
parent 24536 d09262d6ec23
child 24542 9fbda55c68d7
child 24548 c780a63f61ca
dirstate: don't require exact case when adding dirs on icasefs (issue4578) We don't require it when adding files on a case insensitive filesystem, so don't require it to add directories for consistency. The problem with the previous code was that _walkexplicit() was only returning the normalized directory. The file(s) in the directory are then appended, and passed to the matcher. But if the user asks for 'capsdir1/capsdir', the matcher will not accept 'CapsDir1/CapsDir/AbC.txt', and the name is dropped. Matching based on the non-normalized name is required. If not normalizing, skip the extra string building for efficiency. '.' is replaced with '' so that the path being tested when no file is specified, isn't prefixed with './' (and therefore fail the match).
mercurial/dirstate.py
tests/test-add.t
--- a/mercurial/dirstate.py	Tue Mar 31 11:58:14 2015 -0700
+++ b/mercurial/dirstate.py	Tue Mar 31 11:11:39 2015 -0400
@@ -651,7 +651,7 @@
                         results[nf] = None
                     if matchedir:
                         matchedir(nf)
-                    foundadd(nf)
+                    foundadd((nf, ff))
                 elif kind == regkind or kind == lnkkind:
                     results[nf] = st
                 else:
@@ -727,15 +727,16 @@
         results, work, dirsnotfound = self._walkexplicit(match, subrepos)
 
         skipstep3 = skipstep3 and not (work or dirsnotfound)
-        work = [d for d in work if not dirignore(d)]
+        work = [d for d in work if not dirignore(d[0])]
         wadd = work.append
 
         # step 2: visit subdirectories
         while work:
-            nd = work.pop()
+            nd, d = work.pop()
             skip = None
             if nd == '.':
                 nd = ''
+                d = ''
             else:
                 skip = '.hg'
             try:
@@ -748,21 +749,23 @@
             for f, kind, st in entries:
                 if normalize:
                     nf = normalize(nd and (nd + "/" + f) or f, True, True)
+                    f = d and (d + "/" + f) or f
                 else:
                     nf = nd and (nd + "/" + f) or f
+                    f = nf
                 if nf not in results:
                     if kind == dirkind:
                         if not ignore(nf):
                             if matchtdir:
                                 matchtdir(nf)
-                            wadd(nf)
+                            wadd((nf, f))
                         if nf in dmap and (matchalways or matchfn(nf)):
                             results[nf] = None
                     elif kind == regkind or kind == lnkkind:
                         if nf in dmap:
                             if matchalways or matchfn(nf):
                                 results[nf] = st
-                        elif (matchalways or matchfn(nf)) and not ignore(nf):
+                        elif (matchalways or matchfn(f)) and not ignore(nf):
                             results[nf] = st
                     elif nf in dmap and (matchalways or matchfn(nf)):
                         results[nf] = None
--- a/tests/test-add.t	Tue Mar 31 11:58:14 2015 -0700
+++ b/tests/test-add.t	Tue Mar 31 11:11:39 2015 -0400
@@ -169,4 +169,16 @@
   $ cat d
   file d
 
+Test that adding a directory doesn't require case matching (issue4578)
+#if icasefs
+  $ mkdir -p CapsDir1/CapsDir
+  $ echo abc > CapsDir1/CapsDir/AbC.txt
+  $ mkdir CapsDir1/CapsDir/SubDir
+  $ echo def > CapsDir1/CapsDir/SubDir/Def.txt
+
+  $ hg add -v capsdir1/capsdir
+  adding CapsDir1/CapsDir/AbC.txt (glob)
+  adding CapsDir1/CapsDir/SubDir/Def.txt (glob)
+#endif
+
   $ cd ..