dir: report number of visited directories and paths with trace2
[git] / t / t7063-status-untracked-cache.sh
1 #!/bin/sh
2
3 test_description='test untracked cache'
4
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 . ./test-lib.sh
9
10 # On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
11 # is updated lazily after contents in the directory changes, which
12 # forces the untracked cache code to take the slow path.  A test
13 # that wants to make sure that the fast path works correctly should
14 # call this helper to make mtime of the containing directory in sync
15 # with the reality before checking the fast path behaviour.
16 #
17 # See <20160803174522.5571-1-pclouds@gmail.com> if you want to know
18 # more.
19
20 GIT_FORCE_UNTRACKED_CACHE=true
21 export GIT_FORCE_UNTRACKED_CACHE
22
23 sync_mtime () {
24         find . -type d -exec ls -ld {} + >/dev/null
25 }
26
27 avoid_racy() {
28         sleep 1
29 }
30
31 status_is_clean() {
32         git status --porcelain >../status.actual &&
33         test_must_be_empty ../status.actual
34 }
35
36 # Ignore_Untracked_Cache, abbreviated to 3 letters because then people can
37 # compare commands side-by-side, e.g.
38 #    iuc status --porcelain >expect &&
39 #    git status --porcelain >actual &&
40 #    test_cmp expect actual
41 iuc () {
42         git ls-files -s >../current-index-entries
43         git ls-files -t | sed -ne s/^S.//p >../current-sparse-entries
44
45         GIT_INDEX_FILE=.git/tmp_index
46         export GIT_INDEX_FILE
47         git update-index --index-info <../current-index-entries
48         git update-index --skip-worktree $(cat ../current-sparse-entries)
49
50         git -c core.untrackedCache=false "$@"
51         ret=$?
52
53         rm ../current-index-entries
54         rm $GIT_INDEX_FILE
55         unset GIT_INDEX_FILE
56
57         return $ret
58 }
59
60 get_relevant_traces () {
61         # From the GIT_TRACE2_PERF data of the form
62         #    $TIME $FILE:$LINE | d0 | main | data | r1 | ? | ? | read_directo | $RELEVANT_STAT
63         # extract the $RELEVANT_STAT fields.  We don't care about region_enter
64         # or region_leave, or stats for things outside read_directory.
65         INPUT_FILE=$1
66         OUTPUT_FILE=$2
67         grep data.*read_directo $INPUT_FILE |
68             cut -d "|" -f 9 |
69             grep -v visited \
70             >"$OUTPUT_FILE"
71 }
72
73
74 test_lazy_prereq UNTRACKED_CACHE '
75         { git update-index --test-untracked-cache; ret=$?; } &&
76         test $ret -ne 1
77 '
78
79 if ! test_have_prereq UNTRACKED_CACHE; then
80         skip_all='This system does not support untracked cache'
81         test_done
82 fi
83
84 test_expect_success 'core.untrackedCache is unset' '
85         test_must_fail git config --get core.untrackedCache
86 '
87
88 test_expect_success 'setup' '
89         git init worktree &&
90         cd worktree &&
91         mkdir done dtwo dthree &&
92         touch one two three done/one dtwo/two dthree/three &&
93         git add one two done/one &&
94         : >.git/info/exclude &&
95         git update-index --untracked-cache &&
96         test_oid_cache <<-EOF
97         root sha1:e6fcc8f2ee31bae321d66afd183fcb7237afae6e
98         root sha256:b90c672088c015b9c83876e919da311bad4cd39639fb139f988af6a11493b974
99
100         exclude sha1:13263c0978fb9fad16b2d580fb800b6d811c3ff0
101         exclude sha256:fe4aaa1bbbbce4cb8f73426748a14c5ad6026b26f90505a0bf2494b165a5b76c
102
103         done sha1:1946f0437f90c5005533cbe1736a6451ca301714
104         done sha256:7f079501d79f665b3acc50f5e0e9e94509084d5032ac20113a37dd5029b757cc
105         EOF
106 '
107
108 test_expect_success 'untracked cache is empty' '
109         test-tool dump-untracked-cache >../actual &&
110         cat >../expect-empty <<EOF &&
111 info/exclude $ZERO_OID
112 core.excludesfile $ZERO_OID
113 exclude_per_dir .gitignore
114 flags 00000006
115 EOF
116         test_cmp ../expect-empty ../actual
117 '
118
119 cat >../status.expect <<EOF &&
120 A  done/one
121 A  one
122 A  two
123 ?? dthree/
124 ?? dtwo/
125 ?? three
126 EOF
127
128 cat >../dump.expect <<EOF &&
129 info/exclude $EMPTY_BLOB
130 core.excludesfile $ZERO_OID
131 exclude_per_dir .gitignore
132 flags 00000006
133 / $ZERO_OID recurse valid
134 dthree/
135 dtwo/
136 three
137 /done/ $ZERO_OID recurse valid
138 /dthree/ $ZERO_OID recurse check_only valid
139 three
140 /dtwo/ $ZERO_OID recurse check_only valid
141 two
142 EOF
143
144 test_expect_success 'status first time (empty cache)' '
145         avoid_racy &&
146         : >../trace.output &&
147         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
148         git status --porcelain >../actual &&
149         iuc status --porcelain >../status.iuc &&
150         test_cmp ../status.expect ../status.iuc &&
151         test_cmp ../status.expect ../actual &&
152         get_relevant_traces ../trace.output ../trace.relevant &&
153         cat >../trace.expect <<EOF &&
154  ....path:
155  ....node-creation:3
156  ....gitignore-invalidation:1
157  ....directory-invalidation:0
158  ....opendir:4
159 EOF
160         test_cmp ../trace.expect ../trace.relevant
161 '
162
163 test_expect_success 'untracked cache after first status' '
164         test-tool dump-untracked-cache >../actual &&
165         test_cmp ../dump.expect ../actual
166 '
167
168 test_expect_success 'status second time (fully populated cache)' '
169         avoid_racy &&
170         : >../trace.output &&
171         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
172         git status --porcelain >../actual &&
173         iuc status --porcelain >../status.iuc &&
174         test_cmp ../status.expect ../status.iuc &&
175         test_cmp ../status.expect ../actual &&
176         get_relevant_traces ../trace.output ../trace.relevant &&
177         cat >../trace.expect <<EOF &&
178  ....path:
179  ....node-creation:0
180  ....gitignore-invalidation:0
181  ....directory-invalidation:0
182  ....opendir:0
183 EOF
184         test_cmp ../trace.expect ../trace.relevant
185 '
186
187 test_expect_success 'untracked cache after second status' '
188         test-tool dump-untracked-cache >../actual &&
189         test_cmp ../dump.expect ../actual
190 '
191
192 test_expect_success 'modify in root directory, one dir invalidation' '
193         avoid_racy &&
194         : >four &&
195         : >../trace.output &&
196         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
197         git status --porcelain >../actual &&
198         iuc status --porcelain >../status.iuc &&
199         cat >../status.expect <<EOF &&
200 A  done/one
201 A  one
202 A  two
203 ?? dthree/
204 ?? dtwo/
205 ?? four
206 ?? three
207 EOF
208         test_cmp ../status.expect ../status.iuc &&
209         test_cmp ../status.expect ../actual &&
210         get_relevant_traces ../trace.output ../trace.relevant &&
211         cat >../trace.expect <<EOF &&
212  ....path:
213  ....node-creation:0
214  ....gitignore-invalidation:0
215  ....directory-invalidation:1
216  ....opendir:1
217 EOF
218         test_cmp ../trace.expect ../trace.relevant
219
220 '
221
222 test_expect_success 'verify untracked cache dump' '
223         test-tool dump-untracked-cache >../actual &&
224         cat >../expect <<EOF &&
225 info/exclude $EMPTY_BLOB
226 core.excludesfile $ZERO_OID
227 exclude_per_dir .gitignore
228 flags 00000006
229 / $ZERO_OID recurse valid
230 dthree/
231 dtwo/
232 four
233 three
234 /done/ $ZERO_OID recurse valid
235 /dthree/ $ZERO_OID recurse check_only valid
236 three
237 /dtwo/ $ZERO_OID recurse check_only valid
238 two
239 EOF
240         test_cmp ../expect ../actual
241 '
242
243 test_expect_success 'new .gitignore invalidates recursively' '
244         avoid_racy &&
245         echo four >.gitignore &&
246         : >../trace.output &&
247         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
248         git status --porcelain >../actual &&
249         iuc status --porcelain >../status.iuc &&
250         cat >../status.expect <<EOF &&
251 A  done/one
252 A  one
253 A  two
254 ?? .gitignore
255 ?? dthree/
256 ?? dtwo/
257 ?? three
258 EOF
259         test_cmp ../status.expect ../status.iuc &&
260         test_cmp ../status.expect ../actual &&
261         get_relevant_traces ../trace.output ../trace.relevant &&
262         cat >../trace.expect <<EOF &&
263  ....path:
264  ....node-creation:0
265  ....gitignore-invalidation:1
266  ....directory-invalidation:1
267  ....opendir:4
268 EOF
269         test_cmp ../trace.expect ../trace.relevant
270
271 '
272
273 test_expect_success 'verify untracked cache dump' '
274         test-tool dump-untracked-cache >../actual &&
275         cat >../expect <<EOF &&
276 info/exclude $EMPTY_BLOB
277 core.excludesfile $ZERO_OID
278 exclude_per_dir .gitignore
279 flags 00000006
280 / $(test_oid root) recurse valid
281 .gitignore
282 dthree/
283 dtwo/
284 three
285 /done/ $ZERO_OID recurse valid
286 /dthree/ $ZERO_OID recurse check_only valid
287 three
288 /dtwo/ $ZERO_OID recurse check_only valid
289 two
290 EOF
291         test_cmp ../expect ../actual
292 '
293
294 test_expect_success 'new info/exclude invalidates everything' '
295         avoid_racy &&
296         echo three >>.git/info/exclude &&
297         : >../trace.output &&
298         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
299         git status --porcelain >../actual &&
300         iuc status --porcelain >../status.iuc &&
301         cat >../status.expect <<EOF &&
302 A  done/one
303 A  one
304 A  two
305 ?? .gitignore
306 ?? dtwo/
307 EOF
308         test_cmp ../status.expect ../status.iuc &&
309         test_cmp ../status.expect ../actual &&
310         get_relevant_traces ../trace.output ../trace.relevant &&
311         cat >../trace.expect <<EOF &&
312  ....path:
313  ....node-creation:0
314  ....gitignore-invalidation:1
315  ....directory-invalidation:0
316  ....opendir:4
317 EOF
318         test_cmp ../trace.expect ../trace.relevant
319 '
320
321 test_expect_success 'verify untracked cache dump' '
322         test-tool dump-untracked-cache >../actual &&
323         cat >../expect <<EOF &&
324 info/exclude $(test_oid exclude)
325 core.excludesfile $ZERO_OID
326 exclude_per_dir .gitignore
327 flags 00000006
328 / $(test_oid root) recurse valid
329 .gitignore
330 dtwo/
331 /done/ $ZERO_OID recurse valid
332 /dthree/ $ZERO_OID recurse check_only valid
333 /dtwo/ $ZERO_OID recurse check_only valid
334 two
335 EOF
336         test_cmp ../expect ../actual
337 '
338
339 test_expect_success 'move two from tracked to untracked' '
340         git rm --cached two &&
341         test-tool dump-untracked-cache >../actual &&
342         cat >../expect <<EOF &&
343 info/exclude $(test_oid exclude)
344 core.excludesfile $ZERO_OID
345 exclude_per_dir .gitignore
346 flags 00000006
347 / $(test_oid root) recurse
348 /done/ $ZERO_OID recurse valid
349 /dthree/ $ZERO_OID recurse check_only valid
350 /dtwo/ $ZERO_OID recurse check_only valid
351 two
352 EOF
353         test_cmp ../expect ../actual
354 '
355
356 test_expect_success 'status after the move' '
357         : >../trace.output &&
358         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
359         git status --porcelain >../actual &&
360         iuc status --porcelain >../status.iuc &&
361         cat >../status.expect <<EOF &&
362 A  done/one
363 A  one
364 ?? .gitignore
365 ?? dtwo/
366 ?? two
367 EOF
368         test_cmp ../status.expect ../status.iuc &&
369         test_cmp ../status.expect ../actual &&
370         get_relevant_traces ../trace.output ../trace.relevant &&
371         cat >../trace.expect <<EOF &&
372  ....path:
373  ....node-creation:0
374  ....gitignore-invalidation:0
375  ....directory-invalidation:0
376  ....opendir:1
377 EOF
378         test_cmp ../trace.expect ../trace.relevant
379 '
380
381 test_expect_success 'verify untracked cache dump' '
382         test-tool dump-untracked-cache >../actual &&
383         cat >../expect <<EOF &&
384 info/exclude $(test_oid exclude)
385 core.excludesfile $ZERO_OID
386 exclude_per_dir .gitignore
387 flags 00000006
388 / $(test_oid root) recurse valid
389 .gitignore
390 dtwo/
391 two
392 /done/ $ZERO_OID recurse valid
393 /dthree/ $ZERO_OID recurse check_only valid
394 /dtwo/ $ZERO_OID recurse check_only valid
395 two
396 EOF
397         test_cmp ../expect ../actual
398 '
399
400 test_expect_success 'move two from untracked to tracked' '
401         git add two &&
402         test-tool dump-untracked-cache >../actual &&
403         cat >../expect <<EOF &&
404 info/exclude $(test_oid exclude)
405 core.excludesfile $ZERO_OID
406 exclude_per_dir .gitignore
407 flags 00000006
408 / $(test_oid root) recurse
409 /done/ $ZERO_OID recurse valid
410 /dthree/ $ZERO_OID recurse check_only valid
411 /dtwo/ $ZERO_OID recurse check_only valid
412 two
413 EOF
414         test_cmp ../expect ../actual
415 '
416
417 test_expect_success 'status after the move' '
418         : >../trace.output &&
419         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
420         git status --porcelain >../actual &&
421         iuc status --porcelain >../status.iuc &&
422         cat >../status.expect <<EOF &&
423 A  done/one
424 A  one
425 A  two
426 ?? .gitignore
427 ?? dtwo/
428 EOF
429         test_cmp ../status.expect ../status.iuc &&
430         test_cmp ../status.expect ../actual &&
431         get_relevant_traces ../trace.output ../trace.relevant &&
432         cat >../trace.expect <<EOF &&
433  ....path:
434  ....node-creation:0
435  ....gitignore-invalidation:0
436  ....directory-invalidation:0
437  ....opendir:1
438 EOF
439         test_cmp ../trace.expect ../trace.relevant
440 '
441
442 test_expect_success 'verify untracked cache dump' '
443         test-tool dump-untracked-cache >../actual &&
444         cat >../expect <<EOF &&
445 info/exclude $(test_oid exclude)
446 core.excludesfile $ZERO_OID
447 exclude_per_dir .gitignore
448 flags 00000006
449 / $(test_oid root) recurse valid
450 .gitignore
451 dtwo/
452 /done/ $ZERO_OID recurse valid
453 /dthree/ $ZERO_OID recurse check_only valid
454 /dtwo/ $ZERO_OID recurse check_only valid
455 two
456 EOF
457         test_cmp ../expect ../actual
458 '
459
460 test_expect_success 'set up for sparse checkout testing' '
461         echo two >done/.gitignore &&
462         echo three >>done/.gitignore &&
463         echo two >done/two &&
464         git add -f done/two done/.gitignore &&
465         git commit -m "first commit"
466 '
467
468 test_expect_success 'status after commit' '
469         : >../trace.output &&
470         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
471         git status --porcelain >../actual &&
472         iuc status --porcelain >../status.iuc &&
473         cat >../status.expect <<EOF &&
474 ?? .gitignore
475 ?? dtwo/
476 EOF
477         test_cmp ../status.expect ../status.iuc &&
478         test_cmp ../status.expect ../actual &&
479         get_relevant_traces ../trace.output ../trace.relevant &&
480         cat >../trace.expect <<EOF &&
481  ....path:
482  ....node-creation:0
483  ....gitignore-invalidation:0
484  ....directory-invalidation:0
485  ....opendir:2
486 EOF
487         test_cmp ../trace.expect ../trace.relevant
488 '
489
490 test_expect_success 'untracked cache correct after commit' '
491         test-tool dump-untracked-cache >../actual &&
492         cat >../expect <<EOF &&
493 info/exclude $(test_oid exclude)
494 core.excludesfile $ZERO_OID
495 exclude_per_dir .gitignore
496 flags 00000006
497 / $(test_oid root) recurse valid
498 .gitignore
499 dtwo/
500 /done/ $ZERO_OID recurse valid
501 /dthree/ $ZERO_OID recurse check_only valid
502 /dtwo/ $ZERO_OID recurse check_only valid
503 two
504 EOF
505         test_cmp ../expect ../actual
506 '
507
508 test_expect_success 'set up sparse checkout' '
509         echo "done/[a-z]*" >.git/info/sparse-checkout &&
510         test_config core.sparsecheckout true &&
511         git checkout main &&
512         git update-index --force-untracked-cache &&
513         git status --porcelain >/dev/null && # prime the cache
514         test_path_is_missing done/.gitignore &&
515         test_path_is_file done/one
516 '
517
518 test_expect_success 'create/modify files, some of which are gitignored' '
519         echo two bis >done/two &&
520         echo three >done/three && # three is gitignored
521         echo four >done/four && # four is gitignored at a higher level
522         echo five >done/five && # five is not gitignored
523         echo test >base && #we need to ensure that the root dir is touched
524         rm base &&
525         sync_mtime
526 '
527
528 test_expect_success 'test sparse status with untracked cache' '
529         : >../trace.output &&
530         avoid_racy &&
531         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
532         git status --porcelain >../status.actual &&
533         iuc status --porcelain >../status.iuc &&
534         cat >../status.expect <<EOF &&
535  M done/two
536 ?? .gitignore
537 ?? done/five
538 ?? dtwo/
539 EOF
540         test_cmp ../status.expect ../status.iuc &&
541         test_cmp ../status.expect ../status.actual &&
542         get_relevant_traces ../trace.output ../trace.relevant &&
543         cat >../trace.expect <<EOF &&
544  ....path:
545  ....node-creation:0
546  ....gitignore-invalidation:1
547  ....directory-invalidation:2
548  ....opendir:2
549 EOF
550         test_cmp ../trace.expect ../trace.relevant
551 '
552
553 test_expect_success 'untracked cache correct after status' '
554         test-tool dump-untracked-cache >../actual &&
555         cat >../expect <<EOF &&
556 info/exclude $(test_oid exclude)
557 core.excludesfile $ZERO_OID
558 exclude_per_dir .gitignore
559 flags 00000006
560 / $(test_oid root) recurse valid
561 .gitignore
562 dtwo/
563 /done/ $(test_oid done) recurse valid
564 five
565 /dthree/ $ZERO_OID recurse check_only valid
566 /dtwo/ $ZERO_OID recurse check_only valid
567 two
568 EOF
569         test_cmp ../expect ../actual
570 '
571
572 test_expect_success 'test sparse status again with untracked cache' '
573         avoid_racy &&
574         : >../trace.output &&
575         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
576         git status --porcelain >../status.actual &&
577         iuc status --porcelain >../status.iuc &&
578         cat >../status.expect <<EOF &&
579  M done/two
580 ?? .gitignore
581 ?? done/five
582 ?? dtwo/
583 EOF
584         test_cmp ../status.expect ../status.iuc &&
585         test_cmp ../status.expect ../status.actual &&
586         get_relevant_traces ../trace.output ../trace.relevant &&
587         cat >../trace.expect <<EOF &&
588  ....path:
589  ....node-creation:0
590  ....gitignore-invalidation:0
591  ....directory-invalidation:0
592  ....opendir:0
593 EOF
594         test_cmp ../trace.expect ../trace.relevant
595 '
596
597 test_expect_success 'set up for test of subdir and sparse checkouts' '
598         mkdir done/sub &&
599         mkdir done/sub/sub &&
600         echo "sub" > done/sub/sub/file
601 '
602
603 test_expect_success 'test sparse status with untracked cache and subdir' '
604         avoid_racy &&
605         : >../trace.output &&
606         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
607         git status --porcelain >../status.actual &&
608         iuc status --porcelain >../status.iuc &&
609         cat >../status.expect <<EOF &&
610  M done/two
611 ?? .gitignore
612 ?? done/five
613 ?? done/sub/
614 ?? dtwo/
615 EOF
616         test_cmp ../status.expect ../status.iuc &&
617         test_cmp ../status.expect ../status.actual &&
618         get_relevant_traces ../trace.output ../trace.relevant &&
619         cat >../trace.expect <<EOF &&
620  ....path:
621  ....node-creation:2
622  ....gitignore-invalidation:0
623  ....directory-invalidation:1
624  ....opendir:3
625 EOF
626         test_cmp ../trace.expect ../trace.relevant
627 '
628
629 test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
630         test-tool dump-untracked-cache >../actual &&
631         cat >../expect-from-test-dump <<EOF &&
632 info/exclude $(test_oid exclude)
633 core.excludesfile $ZERO_OID
634 exclude_per_dir .gitignore
635 flags 00000006
636 / $(test_oid root) recurse valid
637 .gitignore
638 dtwo/
639 /done/ $(test_oid done) recurse valid
640 five
641 sub/
642 /done/sub/ $ZERO_OID recurse check_only valid
643 sub/
644 /done/sub/sub/ $ZERO_OID recurse check_only valid
645 file
646 /dthree/ $ZERO_OID recurse check_only valid
647 /dtwo/ $ZERO_OID recurse check_only valid
648 two
649 EOF
650         test_cmp ../expect-from-test-dump ../actual
651 '
652
653 test_expect_success 'test sparse status again with untracked cache and subdir' '
654         avoid_racy &&
655         : >../trace.output &&
656         GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
657         git status --porcelain >../status.actual &&
658         iuc status --porcelain >../status.iuc &&
659         test_cmp ../status.expect ../status.iuc &&
660         test_cmp ../status.expect ../status.actual &&
661         get_relevant_traces ../trace.output ../trace.relevant &&
662         cat >../trace.expect <<EOF &&
663  ....path:
664  ....node-creation:0
665  ....gitignore-invalidation:0
666  ....directory-invalidation:0
667  ....opendir:0
668 EOF
669         test_cmp ../trace.expect ../trace.relevant
670 '
671
672 test_expect_success 'move entry in subdir from untracked to cached' '
673         git add dtwo/two &&
674         git status --porcelain >../status.actual &&
675         iuc status --porcelain >../status.iuc &&
676         cat >../status.expect <<EOF &&
677  M done/two
678 A  dtwo/two
679 ?? .gitignore
680 ?? done/five
681 ?? done/sub/
682 EOF
683         test_cmp ../status.expect ../status.iuc &&
684         test_cmp ../status.expect ../status.actual
685 '
686
687 test_expect_success 'move entry in subdir from cached to untracked' '
688         git rm --cached dtwo/two &&
689         git status --porcelain >../status.actual &&
690         iuc status --porcelain >../status.iuc &&
691         cat >../status.expect <<EOF &&
692  M done/two
693 ?? .gitignore
694 ?? done/five
695 ?? done/sub/
696 ?? dtwo/
697 EOF
698         test_cmp ../status.expect ../status.iuc &&
699         test_cmp ../status.expect ../status.actual
700 '
701
702 test_expect_success '--no-untracked-cache removes the cache' '
703         git update-index --no-untracked-cache &&
704         test-tool dump-untracked-cache >../actual &&
705         echo "no untracked cache" >../expect-no-uc &&
706         test_cmp ../expect-no-uc ../actual
707 '
708
709 test_expect_success 'git status does not change anything' '
710         git status &&
711         test-tool dump-untracked-cache >../actual &&
712         test_cmp ../expect-no-uc ../actual
713 '
714
715 test_expect_success 'setting core.untrackedCache to true and using git status creates the cache' '
716         git config core.untrackedCache true &&
717         test-tool dump-untracked-cache >../actual &&
718         test_cmp ../expect-no-uc ../actual &&
719         git status &&
720         test-tool dump-untracked-cache >../actual &&
721         test_cmp ../expect-from-test-dump ../actual
722 '
723
724 test_expect_success 'using --no-untracked-cache does not fail when core.untrackedCache is true' '
725         git update-index --no-untracked-cache &&
726         test-tool dump-untracked-cache >../actual &&
727         test_cmp ../expect-no-uc ../actual &&
728         git update-index --untracked-cache &&
729         test-tool dump-untracked-cache >../actual &&
730         test_cmp ../expect-empty ../actual
731 '
732
733 test_expect_success 'setting core.untrackedCache to false and using git status removes the cache' '
734         git config core.untrackedCache false &&
735         test-tool dump-untracked-cache >../actual &&
736         test_cmp ../expect-empty ../actual &&
737         git status &&
738         test-tool dump-untracked-cache >../actual &&
739         test_cmp ../expect-no-uc ../actual
740 '
741
742 test_expect_success 'using --untracked-cache does not fail when core.untrackedCache is false' '
743         git update-index --untracked-cache &&
744         test-tool dump-untracked-cache >../actual &&
745         test_cmp ../expect-empty ../actual
746 '
747
748 test_expect_success 'setting core.untrackedCache to keep' '
749         git config core.untrackedCache keep &&
750         git update-index --untracked-cache &&
751         test-tool dump-untracked-cache >../actual &&
752         test_cmp ../expect-empty ../actual &&
753         git status &&
754         test-tool dump-untracked-cache >../actual &&
755         test_cmp ../expect-from-test-dump ../actual &&
756         git update-index --no-untracked-cache &&
757         test-tool dump-untracked-cache >../actual &&
758         test_cmp ../expect-no-uc ../actual &&
759         git update-index --force-untracked-cache &&
760         test-tool dump-untracked-cache >../actual &&
761         test_cmp ../expect-empty ../actual &&
762         git status &&
763         test-tool dump-untracked-cache >../actual &&
764         test_cmp ../expect-from-test-dump ../actual
765 '
766
767 test_expect_success 'test ident field is working' '
768         mkdir ../other_worktree &&
769         cp -R done dthree dtwo four three ../other_worktree &&
770         GIT_WORK_TREE=../other_worktree git status 2>../err &&
771         echo "warning: untracked cache is disabled on this system or location" >../expect &&
772         test_cmp ../expect ../err
773 '
774
775 test_expect_success 'untracked cache survives a checkout' '
776         git commit --allow-empty -m empty &&
777         test-tool dump-untracked-cache >../before &&
778         test_when_finished  "git checkout main" &&
779         git checkout -b other_branch &&
780         test-tool dump-untracked-cache >../after &&
781         test_cmp ../before ../after &&
782         test_commit test &&
783         test-tool dump-untracked-cache >../before &&
784         git checkout main &&
785         test-tool dump-untracked-cache >../after &&
786         test_cmp ../before ../after
787 '
788
789 test_expect_success 'untracked cache survives a commit' '
790         test-tool dump-untracked-cache >../before &&
791         git add done/two &&
792         git commit -m commit &&
793         test-tool dump-untracked-cache >../after &&
794         test_cmp ../before ../after
795 '
796
797 test_expect_success 'teardown worktree' '
798         cd ..
799 '
800
801 test_expect_success SYMLINKS 'setup worktree for symlink test' '
802         git init worktree-symlink &&
803         cd worktree-symlink &&
804         git config core.untrackedCache true &&
805         mkdir one two &&
806         touch one/file two/file &&
807         git add one/file two/file &&
808         git commit -m"first commit" &&
809         git rm -rf one &&
810         ln -s two one &&
811         git add one &&
812         git commit -m"second commit"
813 '
814
815 test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=true' '
816         git checkout HEAD~ &&
817         status_is_clean &&
818         status_is_clean &&
819         git checkout main &&
820         avoid_racy &&
821         status_is_clean &&
822         status_is_clean
823 '
824
825 test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=false' '
826         git config core.untrackedCache false &&
827         git checkout HEAD~ &&
828         status_is_clean &&
829         status_is_clean &&
830         git checkout main &&
831         avoid_racy &&
832         status_is_clean &&
833         status_is_clean
834 '
835
836 test_expect_success 'setup worktree for non-symlink test' '
837         git init worktree-non-symlink &&
838         cd worktree-non-symlink &&
839         git config core.untrackedCache true &&
840         mkdir one two &&
841         touch one/file two/file &&
842         git add one/file two/file &&
843         git commit -m"first commit" &&
844         git rm -rf one &&
845         cp two/file one &&
846         git add one &&
847         git commit -m"second commit"
848 '
849
850 test_expect_success '"status" after file replacement should be clean with UC=true' '
851         git checkout HEAD~ &&
852         status_is_clean &&
853         status_is_clean &&
854         git checkout main &&
855         avoid_racy &&
856         status_is_clean &&
857         test-tool dump-untracked-cache >../actual &&
858         grep -F "recurse valid" ../actual >../actual.grep &&
859         cat >../expect.grep <<EOF &&
860 / $ZERO_OID recurse valid
861 /two/ $ZERO_OID recurse valid
862 EOF
863         status_is_clean &&
864         test_cmp ../expect.grep ../actual.grep
865 '
866
867 test_expect_success '"status" after file replacement should be clean with UC=false' '
868         git config core.untrackedCache false &&
869         git checkout HEAD~ &&
870         status_is_clean &&
871         status_is_clean &&
872         git checkout main &&
873         avoid_racy &&
874         status_is_clean &&
875         status_is_clean
876 '
877
878 test_done