git-p4: honor core.ignorecase when using P4 client specs

Perforce depot may record paths in mixed cases, e.g. "p4 files" may show that there are these two paths: //depot/Path/to/file1 //depot/pATH/to/file2 and with "p4" or "p4v", these end up in the same directory, e.g. //depot/Path/to/file1 //depot/Path/to/file2 which is the desired outcome on case insensitive systems. If git-p4 is used with client spec "//depot/Path/...", however, then all files not matching the case in the client spec are ignored (in the example above "//depot/pATH/to/file2"). Fix this by using the path case that appears first in lexicographical order when core.ignorecase is set to true. This behavior is consistent with "p4" and "p4v". Signed-off-by: Lars Schneider <larsxschneider@gmail.com> Acked-by: Luke Diamand <luke@diamand.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Lars Schneider committed Aug 28, 2015 at 14:00 UTC a0a50d873c575876c6a5c185ac1c64b9a33e2fb3
2 files changed +207
git-p4.py
+7
@@ -1950,10 +1950,14 @@ class View(object):
1950 if "unmap" in res:
1951 # it will list all of them, but only one not unmap-ped
1952 continue
1953 + if gitConfigBool("core.ignorecase"):
1954 + res['depotFile'] = res['depotFile'].lower()
1955 self.client_spec_path_cache[res['depotFile']] = self.convert_client_path(res["clientFile"])
1956
1957 # not found files or unmap files set to ""
1958 for depotFile in fileArgs:
1959 + if gitConfigBool("core.ignorecase"):
1960 + depotFile = depotFile.lower()
1961 if depotFile not in self.client_spec_path_cache:
1962 self.client_spec_path_cache[depotFile] = ""
1963
@@ -1962,6 +1966,9 @@ class View(object):
1966 depot file should live. Returns "" if the file should
1967 not be mapped in the client."""
1968
1969 + if gitConfigBool("core.ignorecase"):
1970 + depot_path = depot_path.lower()
1971 +
1972 if depot_path in self.client_spec_path_cache:
1973 return self.client_spec_path_cache[depot_path]
1974
t/t9821-git-p4-path-variations.sh new
+200
@@ -0,0 +1,200 @@
1 +#!/bin/sh
2 +
3 +test_description='Clone repositories with path case variations'
4 +
5 +. ./lib-git-p4.sh
6 +
7 +test_expect_success 'start p4d with case folding enabled' '
8 + start_p4d -C1
9 +'
10 +
11 +test_expect_success 'Create a repo with path case variations' '
12 + client_view "//depot/... //client/..." &&
13 + (
14 + cd "$cli" &&
15 +
16 + mkdir -p Path/to &&
17 + >Path/to/File2.txt &&
18 + p4 add Path/to/File2.txt &&
19 + p4 submit -d "Add file2" &&
20 + rm -rf Path &&
21 +
22 + mkdir -p path/TO &&
23 + >path/TO/file1.txt &&
24 + p4 add path/TO/file1.txt &&
25 + p4 submit -d "Add file1" &&
26 + rm -rf path &&
27 +
28 + mkdir -p path/to &&
29 + >path/to/file3.txt &&
30 + p4 add path/to/file3.txt &&
31 + p4 submit -d "Add file3" &&
32 + rm -rf path &&
33 +
34 + mkdir -p x-outside-spec &&
35 + >x-outside-spec/file4.txt &&
36 + p4 add x-outside-spec/file4.txt &&
37 + p4 submit -d "Add file4" &&
38 + rm -rf x-outside-spec
39 + )
40 +'
41 +
42 +test_expect_success 'Clone root' '
43 + client_view "//depot/... //client/..." &&
44 + test_when_finished cleanup_git &&
45 + (
46 + cd "$git" &&
47 + git init . &&
48 + git config core.ignorecase false &&
49 + git p4 clone --use-client-spec --destination="$git" //depot &&
50 + # This method is used instead of "test -f" to ensure the case is
51 + # checked even if the test is executed on case-insensitive file systems.
52 + # All files are there as expected although the path cases look random.
53 + cat >expect <<-\EOF &&
54 + Path/to/File2.txt
55 + path/TO/file1.txt
56 + path/to/file3.txt
57 + x-outside-spec/file4.txt
58 + EOF
59 + git ls-files >actual &&
60 + test_cmp expect actual
61 + )
62 +'
63 +
64 +test_expect_success 'Clone root (ignorecase)' '
65 + client_view "//depot/... //client/..." &&
66 + test_when_finished cleanup_git &&
67 + (
68 + cd "$git" &&
69 + git init . &&
70 + git config core.ignorecase true &&
71 + git p4 clone --use-client-spec --destination="$git" //depot &&
72 + # This method is used instead of "test -f" to ensure the case is
73 + # checked even if the test is executed on case-insensitive file systems.
74 + # All files are there as expected although the path cases look random.
75 + cat >expect <<-\EOF &&
76 + path/TO/File2.txt
77 + path/TO/file1.txt
78 + path/TO/file3.txt
79 + x-outside-spec/file4.txt
80 + EOF
81 + git ls-files >actual &&
82 + test_cmp expect actual
83 + )
84 +'
85 +
86 +test_expect_success 'Clone root and ignore one file' '
87 + client_view \
88 + "//depot/... //client/..." \
89 + "-//depot/path/TO/file1.txt //client/path/TO/file1.txt" &&
90 + test_when_finished cleanup_git &&
91 + (
92 + cd "$git" &&
93 + git init . &&
94 + git config core.ignorecase false &&
95 + git p4 clone --use-client-spec --destination="$git" //depot &&
96 + # We ignore one file in the client spec and all path cases change from
97 + # "TO" to "to"!
98 + cat >expect <<-\EOF &&
99 + Path/to/File2.txt
100 + path/to/file3.txt
101 + x-outside-spec/file4.txt
102 + EOF
103 + git ls-files >actual &&
104 + test_cmp expect actual
105 + )
106 +'
107 +
108 +test_expect_success 'Clone root and ignore one file (ignorecase)' '
109 + client_view \
110 + "//depot/... //client/..." \
111 + "-//depot/path/TO/file1.txt //client/path/TO/file1.txt" &&
112 + test_when_finished cleanup_git &&
113 + (
114 + cd "$git" &&
115 + git init . &&
116 + git config core.ignorecase true &&
117 + git p4 clone --use-client-spec --destination="$git" //depot &&
118 + # We ignore one file in the client spec and all path cases change from
119 + # "TO" to "to"!
120 + cat >expect <<-\EOF &&
121 + Path/to/File2.txt
122 + Path/to/file3.txt
123 + x-outside-spec/file4.txt
124 + EOF
125 + git ls-files >actual &&
126 + test_cmp expect actual
127 + )
128 +'
129 +
130 +test_expect_success 'Clone path' '
131 + client_view "//depot/Path/... //client/..." &&
132 + test_when_finished cleanup_git &&
133 + (
134 + cd "$git" &&
135 + git init . &&
136 + git config core.ignorecase false &&
137 + git p4 clone --use-client-spec --destination="$git" //depot &&
138 + cat >expect <<-\EOF &&
139 + to/File2.txt
140 + EOF
141 + git ls-files >actual &&
142 + test_cmp expect actual
143 + )
144 +'
145 +
146 +test_expect_success 'Clone path (ignorecase)' '
147 + client_view "//depot/Path/... //client/..." &&
148 + test_when_finished cleanup_git &&
149 + (
150 + cd "$git" &&
151 + git init . &&
152 + git config core.ignorecase true &&
153 + git p4 clone --use-client-spec --destination="$git" //depot &&
154 + cat >expect <<-\EOF &&
155 + TO/File2.txt
156 + TO/file1.txt
157 + TO/file3.txt
158 + EOF
159 + git ls-files >actual &&
160 + test_cmp expect actual
161 + )
162 +'
163 +
164 +# It looks like P4 determines the path case based on the first file in
165 +# lexicographical order. Please note the lower case "to" directory for all
166 +# files triggered through the addition of "File0.txt".
167 +test_expect_success 'Add a new file and clone path with new file (ignorecase)' '
168 + client_view "//depot/... //client/..." &&
169 + (
170 + cd "$cli" &&
171 + mkdir -p Path/to &&
172 + >Path/to/File0.txt &&
173 + p4 add Path/to/File0.txt &&
174 + p4 submit -d "Add file" &&
175 + rm -rf Path
176 + ) &&
177 +
178 + client_view "//depot/Path/... //client/..." &&
179 + test_when_finished cleanup_git &&
180 + (
181 + cd "$git" &&
182 + git init . &&
183 + git config core.ignorecase true &&
184 + git p4 clone --use-client-spec --destination="$git" //depot &&
185 + cat >expect <<-\EOF &&
186 + to/File0.txt
187 + to/File2.txt
188 + to/file1.txt
189 + to/file3.txt
190 + EOF
191 + git ls-files >actual &&
192 + test_cmp expect actual
193 + )
194 +'
195 +
196 +test_expect_success 'kill p4d' '
197 + kill_p4d
198 +'
199 +
200 +test_done