Merge branch 'jk/long-error-messages'
[git] / t / t7063-status-untracked-cache.sh
1 #!/bin/sh
2
3 test_description='test untracked cache'
4
5 . ./test-lib.sh
6
7 avoid_racy() {
8         sleep 1
9 }
10
11 # It's fine if git update-index returns an error code other than one,
12 # it'll be caught in the first test.
13 test_lazy_prereq UNTRACKED_CACHE '
14         { git update-index --untracked-cache; ret=$?; } &&
15         test $ret -ne 1
16 '
17
18 if ! test_have_prereq UNTRACKED_CACHE; then
19         skip_all='This system does not support untracked cache'
20         test_done
21 fi
22
23 test_expect_success 'setup' '
24         git init worktree &&
25         cd worktree &&
26         mkdir done dtwo dthree &&
27         touch one two three done/one dtwo/two dthree/three &&
28         git add one two done/one &&
29         : >.git/info/exclude &&
30         git update-index --untracked-cache
31 '
32
33 test_expect_success 'untracked cache is empty' '
34         test-dump-untracked-cache >../actual &&
35         cat >../expect <<EOF &&
36 info/exclude 0000000000000000000000000000000000000000
37 core.excludesfile 0000000000000000000000000000000000000000
38 exclude_per_dir .gitignore
39 flags 00000006
40 EOF
41         test_cmp ../expect ../actual
42 '
43
44 cat >../status.expect <<EOF &&
45 A  done/one
46 A  one
47 A  two
48 ?? dthree/
49 ?? dtwo/
50 ?? three
51 EOF
52
53 cat >../dump.expect <<EOF &&
54 info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
55 core.excludesfile 0000000000000000000000000000000000000000
56 exclude_per_dir .gitignore
57 flags 00000006
58 / 0000000000000000000000000000000000000000 recurse valid
59 dthree/
60 dtwo/
61 three
62 /done/ 0000000000000000000000000000000000000000 recurse valid
63 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
64 three
65 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
66 two
67 EOF
68
69 test_expect_success 'status first time (empty cache)' '
70         avoid_racy &&
71         : >../trace &&
72         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
73         git status --porcelain >../actual &&
74         test_cmp ../status.expect ../actual &&
75         cat >../trace.expect <<EOF &&
76 node creation: 3
77 gitignore invalidation: 1
78 directory invalidation: 0
79 opendir: 4
80 EOF
81         test_cmp ../trace.expect ../trace
82 '
83
84 test_expect_success 'untracked cache after first status' '
85         test-dump-untracked-cache >../actual &&
86         test_cmp ../dump.expect ../actual
87 '
88
89 test_expect_success 'status second time (fully populated cache)' '
90         avoid_racy &&
91         : >../trace &&
92         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
93         git status --porcelain >../actual &&
94         test_cmp ../status.expect ../actual &&
95         cat >../trace.expect <<EOF &&
96 node creation: 0
97 gitignore invalidation: 0
98 directory invalidation: 0
99 opendir: 0
100 EOF
101         test_cmp ../trace.expect ../trace
102 '
103
104 test_expect_success 'untracked cache after second status' '
105         test-dump-untracked-cache >../actual &&
106         test_cmp ../dump.expect ../actual
107 '
108
109 test_expect_success 'modify in root directory, one dir invalidation' '
110         avoid_racy &&
111         : >four &&
112         : >../trace &&
113         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
114         git status --porcelain >../actual &&
115         cat >../status.expect <<EOF &&
116 A  done/one
117 A  one
118 A  two
119 ?? dthree/
120 ?? dtwo/
121 ?? four
122 ?? three
123 EOF
124         test_cmp ../status.expect ../actual &&
125         cat >../trace.expect <<EOF &&
126 node creation: 0
127 gitignore invalidation: 0
128 directory invalidation: 1
129 opendir: 1
130 EOF
131         test_cmp ../trace.expect ../trace
132
133 '
134
135 test_expect_success 'verify untracked cache dump' '
136         test-dump-untracked-cache >../actual &&
137         cat >../expect <<EOF &&
138 info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
139 core.excludesfile 0000000000000000000000000000000000000000
140 exclude_per_dir .gitignore
141 flags 00000006
142 / 0000000000000000000000000000000000000000 recurse valid
143 dthree/
144 dtwo/
145 four
146 three
147 /done/ 0000000000000000000000000000000000000000 recurse valid
148 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
149 three
150 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
151 two
152 EOF
153         test_cmp ../expect ../actual
154 '
155
156 test_expect_success 'new .gitignore invalidates recursively' '
157         avoid_racy &&
158         echo four >.gitignore &&
159         : >../trace &&
160         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
161         git status --porcelain >../actual &&
162         cat >../status.expect <<EOF &&
163 A  done/one
164 A  one
165 A  two
166 ?? .gitignore
167 ?? dthree/
168 ?? dtwo/
169 ?? three
170 EOF
171         test_cmp ../status.expect ../actual &&
172         cat >../trace.expect <<EOF &&
173 node creation: 0
174 gitignore invalidation: 1
175 directory invalidation: 1
176 opendir: 4
177 EOF
178         test_cmp ../trace.expect ../trace
179
180 '
181
182 test_expect_success 'verify untracked cache dump' '
183         test-dump-untracked-cache >../actual &&
184         cat >../expect <<EOF &&
185 info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
186 core.excludesfile 0000000000000000000000000000000000000000
187 exclude_per_dir .gitignore
188 flags 00000006
189 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
190 .gitignore
191 dthree/
192 dtwo/
193 three
194 /done/ 0000000000000000000000000000000000000000 recurse valid
195 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
196 three
197 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
198 two
199 EOF
200         test_cmp ../expect ../actual
201 '
202
203 test_expect_success 'new info/exclude invalidates everything' '
204         avoid_racy &&
205         echo three >>.git/info/exclude &&
206         : >../trace &&
207         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
208         git status --porcelain >../actual &&
209         cat >../status.expect <<EOF &&
210 A  done/one
211 A  one
212 A  two
213 ?? .gitignore
214 ?? dtwo/
215 EOF
216         test_cmp ../status.expect ../actual &&
217         cat >../trace.expect <<EOF &&
218 node creation: 0
219 gitignore invalidation: 1
220 directory invalidation: 0
221 opendir: 4
222 EOF
223         test_cmp ../trace.expect ../trace
224 '
225
226 test_expect_success 'verify untracked cache dump' '
227         test-dump-untracked-cache >../actual &&
228         cat >../expect <<EOF &&
229 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
230 core.excludesfile 0000000000000000000000000000000000000000
231 exclude_per_dir .gitignore
232 flags 00000006
233 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
234 .gitignore
235 dtwo/
236 /done/ 0000000000000000000000000000000000000000 recurse valid
237 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
238 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
239 two
240 EOF
241         test_cmp ../expect ../actual
242 '
243
244 test_expect_success 'move two from tracked to untracked' '
245         git rm --cached two &&
246         test-dump-untracked-cache >../actual &&
247         cat >../expect <<EOF &&
248 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
249 core.excludesfile 0000000000000000000000000000000000000000
250 exclude_per_dir .gitignore
251 flags 00000006
252 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
253 /done/ 0000000000000000000000000000000000000000 recurse valid
254 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
255 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
256 two
257 EOF
258         test_cmp ../expect ../actual
259 '
260
261 test_expect_success 'status after the move' '
262         : >../trace &&
263         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
264         git status --porcelain >../actual &&
265         cat >../status.expect <<EOF &&
266 A  done/one
267 A  one
268 ?? .gitignore
269 ?? dtwo/
270 ?? two
271 EOF
272         test_cmp ../status.expect ../actual &&
273         cat >../trace.expect <<EOF &&
274 node creation: 0
275 gitignore invalidation: 0
276 directory invalidation: 0
277 opendir: 1
278 EOF
279         test_cmp ../trace.expect ../trace
280 '
281
282 test_expect_success 'verify untracked cache dump' '
283         test-dump-untracked-cache >../actual &&
284         cat >../expect <<EOF &&
285 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
286 core.excludesfile 0000000000000000000000000000000000000000
287 exclude_per_dir .gitignore
288 flags 00000006
289 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
290 .gitignore
291 dtwo/
292 two
293 /done/ 0000000000000000000000000000000000000000 recurse valid
294 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
295 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
296 two
297 EOF
298         test_cmp ../expect ../actual
299 '
300
301 test_expect_success 'move two from untracked to tracked' '
302         git add two &&
303         test-dump-untracked-cache >../actual &&
304         cat >../expect <<EOF &&
305 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
306 core.excludesfile 0000000000000000000000000000000000000000
307 exclude_per_dir .gitignore
308 flags 00000006
309 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
310 /done/ 0000000000000000000000000000000000000000 recurse valid
311 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
312 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
313 two
314 EOF
315         test_cmp ../expect ../actual
316 '
317
318 test_expect_success 'status after the move' '
319         : >../trace &&
320         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
321         git status --porcelain >../actual &&
322         cat >../status.expect <<EOF &&
323 A  done/one
324 A  one
325 A  two
326 ?? .gitignore
327 ?? dtwo/
328 EOF
329         test_cmp ../status.expect ../actual &&
330         cat >../trace.expect <<EOF &&
331 node creation: 0
332 gitignore invalidation: 0
333 directory invalidation: 0
334 opendir: 1
335 EOF
336         test_cmp ../trace.expect ../trace
337 '
338
339 test_expect_success 'verify untracked cache dump' '
340         test-dump-untracked-cache >../actual &&
341         cat >../expect <<EOF &&
342 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
343 core.excludesfile 0000000000000000000000000000000000000000
344 exclude_per_dir .gitignore
345 flags 00000006
346 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
347 .gitignore
348 dtwo/
349 /done/ 0000000000000000000000000000000000000000 recurse valid
350 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
351 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
352 two
353 EOF
354         test_cmp ../expect ../actual
355 '
356
357 test_expect_success 'set up for sparse checkout testing' '
358         echo two >done/.gitignore &&
359         echo three >>done/.gitignore &&
360         echo two >done/two &&
361         git add -f done/two done/.gitignore &&
362         git commit -m "first commit"
363 '
364
365 test_expect_success 'status after commit' '
366         : >../trace &&
367         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
368         git status --porcelain >../actual &&
369         cat >../status.expect <<EOF &&
370 ?? .gitignore
371 ?? dtwo/
372 EOF
373         test_cmp ../status.expect ../actual &&
374         cat >../trace.expect <<EOF &&
375 node creation: 0
376 gitignore invalidation: 0
377 directory invalidation: 0
378 opendir: 1
379 EOF
380         test_cmp ../trace.expect ../trace
381 '
382
383 test_expect_success 'untracked cache correct after commit' '
384         test-dump-untracked-cache >../actual &&
385         cat >../expect <<EOF &&
386 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
387 core.excludesfile 0000000000000000000000000000000000000000
388 exclude_per_dir .gitignore
389 flags 00000006
390 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
391 .gitignore
392 dtwo/
393 /done/ 0000000000000000000000000000000000000000 recurse valid
394 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
395 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
396 two
397 EOF
398         test_cmp ../expect ../actual
399 '
400
401 test_expect_success 'set up sparse checkout' '
402         echo "done/[a-z]*" >.git/info/sparse-checkout &&
403         test_config core.sparsecheckout true &&
404         git checkout master &&
405         git update-index --untracked-cache &&
406         git status --porcelain >/dev/null && # prime the cache
407         test_path_is_missing done/.gitignore &&
408         test_path_is_file done/one
409 '
410
411 test_expect_success 'create files, some of which are gitignored' '
412         echo three >done/three && # three is gitignored
413         echo four >done/four && # four is gitignored at a higher level
414         echo five >done/five # five is not gitignored
415 '
416
417 test_expect_success 'test sparse status with untracked cache' '
418         : >../trace &&
419         avoid_racy &&
420         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
421         git status --porcelain >../status.actual &&
422         cat >../status.expect <<EOF &&
423 ?? .gitignore
424 ?? done/five
425 ?? dtwo/
426 EOF
427         test_cmp ../status.expect ../status.actual &&
428         cat >../trace.expect <<EOF &&
429 node creation: 0
430 gitignore invalidation: 1
431 directory invalidation: 2
432 opendir: 2
433 EOF
434         test_cmp ../trace.expect ../trace
435 '
436
437 test_expect_success 'untracked cache correct after status' '
438         test-dump-untracked-cache >../actual &&
439         cat >../expect <<EOF &&
440 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
441 core.excludesfile 0000000000000000000000000000000000000000
442 exclude_per_dir .gitignore
443 flags 00000006
444 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
445 .gitignore
446 dtwo/
447 /done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
448 five
449 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
450 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
451 two
452 EOF
453         test_cmp ../expect ../actual
454 '
455
456 test_expect_success 'test sparse status again with untracked cache' '
457         avoid_racy &&
458         : >../trace &&
459         GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
460         git status --porcelain >../status.actual &&
461         cat >../status.expect <<EOF &&
462 ?? .gitignore
463 ?? done/five
464 ?? dtwo/
465 EOF
466         test_cmp ../status.expect ../status.actual &&
467         cat >../trace.expect <<EOF &&
468 node creation: 0
469 gitignore invalidation: 0
470 directory invalidation: 0
471 opendir: 0
472 EOF
473         test_cmp ../trace.expect ../trace
474 '
475
476 test_done