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