dir: fix leak when parsing "status.showUntrackedFiles"
[git/gitster.git] / t / t7063-status-untracked-cache.sh
blob13fea7931cddef581cf4a6460aaca4c770e1d287
1 #!/bin/sh
3 test_description='test untracked cache'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 TEST_PASSES_SANITIZE_LEAK=true
9 . ./test-lib.sh
11 # On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
12 # is updated lazily after contents in the directory changes, which
13 # forces the untracked cache code to take the slow path. A test
14 # that wants to make sure that the fast path works correctly should
15 # call this helper to make mtime of the containing directory in sync
16 # with the reality before checking the fast path behaviour.
18 # See <20160803174522.5571-1-pclouds@gmail.com> if you want to know
19 # more.
21 GIT_FORCE_UNTRACKED_CACHE=true
22 export GIT_FORCE_UNTRACKED_CACHE
24 sync_mtime () {
25 find . -type d -exec ls -ld {} + >/dev/null
28 avoid_racy() {
29 sleep 1
32 status_is_clean() {
33 git status --porcelain >../status.actual &&
34 test_must_be_empty ../status.actual
37 # Ignore_Untracked_Cache, abbreviated to 3 letters because then people can
38 # compare commands side-by-side, e.g.
39 # iuc status --porcelain >expect &&
40 # git status --porcelain >actual &&
41 # test_cmp expect actual
42 iuc () {
43 git ls-files -s >../current-index-entries
44 git ls-files -t | sed -ne s/^S.//p >../current-sparse-entries
46 GIT_INDEX_FILE=.git/tmp_index
47 export GIT_INDEX_FILE
48 git update-index --index-info <../current-index-entries
49 git update-index --skip-worktree $(cat ../current-sparse-entries)
51 git -c core.untrackedCache=false "$@"
52 ret=$?
54 rm ../current-index-entries
55 rm $GIT_INDEX_FILE
56 unset GIT_INDEX_FILE
58 return $ret
61 get_relevant_traces () {
62 # From the GIT_TRACE2_PERF data of the form
63 # $TIME $FILE:$LINE | d0 | main | data | r1 | ? | ? | read_directo | $RELEVANT_STAT
64 # extract the $RELEVANT_STAT fields. We don't care about region_enter
65 # or region_leave, or stats for things outside read_directory.
66 INPUT_FILE=$1
67 OUTPUT_FILE=$2
68 grep data.*read_directo $INPUT_FILE |
69 cut -d "|" -f 9 |
70 grep -v visited \
71 >"$OUTPUT_FILE"
75 test_lazy_prereq UNTRACKED_CACHE '
76 { git update-index --test-untracked-cache; ret=$?; } &&
77 test $ret -ne 1
80 if ! test_have_prereq UNTRACKED_CACHE; then
81 skip_all='This system does not support untracked cache'
82 test_done
85 test_expect_success 'core.untrackedCache is unset' '
86 test_must_fail git config --get core.untrackedCache
89 test_expect_success 'setup' '
90 git init --template= worktree &&
91 cd worktree &&
92 mkdir done dtwo dthree &&
93 touch one two three done/one dtwo/two dthree/three &&
94 test-tool chmtime =-300 one two three done/one dtwo/two dthree/three &&
95 test-tool chmtime =-300 done dtwo dthree &&
96 test-tool chmtime =-300 . &&
97 git add one two done/one &&
98 mkdir .git/info &&
99 : >.git/info/exclude &&
100 git update-index --untracked-cache &&
101 test_oid_cache <<-EOF
102 root sha1:e6fcc8f2ee31bae321d66afd183fcb7237afae6e
103 root sha256:b90c672088c015b9c83876e919da311bad4cd39639fb139f988af6a11493b974
105 exclude sha1:13263c0978fb9fad16b2d580fb800b6d811c3ff0
106 exclude sha256:fe4aaa1bbbbce4cb8f73426748a14c5ad6026b26f90505a0bf2494b165a5b76c
108 done sha1:1946f0437f90c5005533cbe1736a6451ca301714
109 done sha256:7f079501d79f665b3acc50f5e0e9e94509084d5032ac20113a37dd5029b757cc
113 test_expect_success 'untracked cache is empty' '
114 test-tool dump-untracked-cache >../actual &&
115 cat >../expect-empty <<EOF &&
116 info/exclude $ZERO_OID
117 core.excludesfile $ZERO_OID
118 exclude_per_dir .gitignore
119 flags 00000006
121 test_cmp ../expect-empty ../actual
124 cat >../status.expect <<EOF &&
125 A done/one
126 A one
127 A two
128 ?? dthree/
129 ?? dtwo/
130 ?? three
133 cat >../dump.expect <<EOF &&
134 info/exclude $EMPTY_BLOB
135 core.excludesfile $ZERO_OID
136 exclude_per_dir .gitignore
137 flags 00000006
138 / $ZERO_OID recurse valid
139 dthree/
140 dtwo/
141 three
142 /done/ $ZERO_OID recurse valid
143 /dthree/ $ZERO_OID recurse check_only valid
144 three
145 /dtwo/ $ZERO_OID recurse check_only valid
149 test_expect_success 'status first time (empty cache)' '
150 : >../trace.output &&
151 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
152 git status --porcelain >../actual &&
153 iuc status --porcelain >../status.iuc &&
154 test_cmp ../status.expect ../status.iuc &&
155 test_cmp ../status.expect ../actual &&
156 get_relevant_traces ../trace.output ../trace.relevant &&
157 cat >../trace.expect <<EOF &&
158 ....path:
159 ....node-creation:3
160 ....gitignore-invalidation:1
161 ....directory-invalidation:0
162 ....opendir:4
164 test_cmp ../trace.expect ../trace.relevant
167 test_expect_success 'untracked cache after first status' '
168 test-tool dump-untracked-cache >../actual &&
169 test_cmp ../dump.expect ../actual
172 test_expect_success 'status second time (fully populated cache)' '
173 : >../trace.output &&
174 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
175 git status --porcelain >../actual &&
176 iuc status --porcelain >../status.iuc &&
177 test_cmp ../status.expect ../status.iuc &&
178 test_cmp ../status.expect ../actual &&
179 get_relevant_traces ../trace.output ../trace.relevant &&
180 cat >../trace.expect <<EOF &&
181 ....path:
182 ....node-creation:0
183 ....gitignore-invalidation:0
184 ....directory-invalidation:0
185 ....opendir:0
187 test_cmp ../trace.expect ../trace.relevant
190 test_expect_success 'untracked cache after second status' '
191 test-tool dump-untracked-cache >../actual &&
192 test_cmp ../dump.expect ../actual
195 cat >../status_uall.expect <<EOF &&
196 A done/one
197 A one
198 A two
199 ?? dthree/three
200 ?? dtwo/two
201 ?? three
204 # Bypassing the untracked cache here is not desirable from an
205 # end-user perspective, but is expected in the current design.
206 # The untracked cache data stored for a -unormal run cannot be
207 # correctly used in a -uall run - it would yield incorrect output.
208 test_expect_success 'untracked cache is bypassed with -uall' '
209 : >../trace.output &&
210 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
211 git status -uall --porcelain >../actual &&
212 iuc status -uall --porcelain >../status.iuc &&
213 test_cmp ../status_uall.expect ../status.iuc &&
214 test_cmp ../status_uall.expect ../actual &&
215 get_relevant_traces ../trace.output ../trace.relevant &&
216 cat >../trace.expect <<EOF &&
217 ....path:
219 test_cmp ../trace.expect ../trace.relevant
222 test_expect_success 'untracked cache remains after bypass' '
223 test-tool dump-untracked-cache >../actual &&
224 test_cmp ../dump.expect ../actual
227 test_expect_success 'if -uall is configured, untracked cache gets populated by default' '
228 test_config status.showuntrackedfiles all &&
229 : >../trace.output &&
230 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
231 git status --porcelain >../actual &&
232 iuc status --porcelain >../status.iuc &&
233 test_cmp ../status_uall.expect ../status.iuc &&
234 test_cmp ../status_uall.expect ../actual &&
235 get_relevant_traces ../trace.output ../trace.relevant &&
236 cat >../trace.expect <<EOF &&
237 ....path:
238 ....node-creation:3
239 ....gitignore-invalidation:1
240 ....directory-invalidation:0
241 ....opendir:4
243 test_cmp ../trace.expect ../trace.relevant
246 cat >../dump_uall.expect <<EOF &&
247 info/exclude $EMPTY_BLOB
248 core.excludesfile $ZERO_OID
249 exclude_per_dir .gitignore
250 flags 00000000
251 / $ZERO_OID recurse valid
252 three
253 /done/ $ZERO_OID recurse valid
254 /dthree/ $ZERO_OID recurse valid
255 three
256 /dtwo/ $ZERO_OID recurse valid
260 test_expect_success 'if -uall was configured, untracked cache is populated' '
261 test-tool dump-untracked-cache >../actual &&
262 test_cmp ../dump_uall.expect ../actual
265 test_expect_success 'if -uall is configured, untracked cache is used by default' '
266 test_config status.showuntrackedfiles all &&
267 : >../trace.output &&
268 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
269 git status --porcelain >../actual &&
270 iuc status --porcelain >../status.iuc &&
271 test_cmp ../status_uall.expect ../status.iuc &&
272 test_cmp ../status_uall.expect ../actual &&
273 get_relevant_traces ../trace.output ../trace.relevant &&
274 cat >../trace.expect <<EOF &&
275 ....path:
276 ....node-creation:0
277 ....gitignore-invalidation:0
278 ....directory-invalidation:0
279 ....opendir:0
281 test_cmp ../trace.expect ../trace.relevant
284 # Bypassing the untracked cache here is not desirable from an
285 # end-user perspective, but is expected in the current design.
286 # The untracked cache data stored for a -all run cannot be
287 # correctly used in a -unormal run - it would yield incorrect
288 # output.
289 test_expect_success 'if -uall is configured, untracked cache is bypassed with -unormal' '
290 test_config status.showuntrackedfiles all &&
291 : >../trace.output &&
292 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
293 git status -unormal --porcelain >../actual &&
294 iuc status -unormal --porcelain >../status.iuc &&
295 test_cmp ../status.expect ../status.iuc &&
296 test_cmp ../status.expect ../actual &&
297 get_relevant_traces ../trace.output ../trace.relevant &&
298 cat >../trace.expect <<EOF &&
299 ....path:
301 test_cmp ../trace.expect ../trace.relevant
304 test_expect_success 'repopulate untracked cache for -unormal' '
305 git status --porcelain
308 test_expect_success 'modify in root directory, one dir invalidation' '
309 : >four &&
310 test-tool chmtime =-240 four &&
311 : >../trace.output &&
312 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
313 git status --porcelain >../actual &&
314 iuc status --porcelain >../status.iuc &&
315 cat >../status.expect <<EOF &&
316 A done/one
317 A one
318 A two
319 ?? dthree/
320 ?? dtwo/
321 ?? four
322 ?? three
324 test_cmp ../status.expect ../status.iuc &&
325 test_cmp ../status.expect ../actual &&
326 get_relevant_traces ../trace.output ../trace.relevant &&
327 cat >../trace.expect <<EOF &&
328 ....path:
329 ....node-creation:0
330 ....gitignore-invalidation:0
331 ....directory-invalidation:1
332 ....opendir:1
334 test_cmp ../trace.expect ../trace.relevant
338 test_expect_success 'verify untracked cache dump' '
339 test-tool dump-untracked-cache >../actual &&
340 cat >../expect <<EOF &&
341 info/exclude $EMPTY_BLOB
342 core.excludesfile $ZERO_OID
343 exclude_per_dir .gitignore
344 flags 00000006
345 / $ZERO_OID recurse valid
346 dthree/
347 dtwo/
348 four
349 three
350 /done/ $ZERO_OID recurse valid
351 /dthree/ $ZERO_OID recurse check_only valid
352 three
353 /dtwo/ $ZERO_OID recurse check_only valid
356 test_cmp ../expect ../actual
359 test_expect_success 'new .gitignore invalidates recursively' '
360 echo four >.gitignore &&
361 : >../trace.output &&
362 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
363 git status --porcelain >../actual &&
364 iuc status --porcelain >../status.iuc &&
365 cat >../status.expect <<EOF &&
366 A done/one
367 A one
368 A two
369 ?? .gitignore
370 ?? dthree/
371 ?? dtwo/
372 ?? three
374 test_cmp ../status.expect ../status.iuc &&
375 test_cmp ../status.expect ../actual &&
376 get_relevant_traces ../trace.output ../trace.relevant &&
377 cat >../trace.expect <<EOF &&
378 ....path:
379 ....node-creation:0
380 ....gitignore-invalidation:1
381 ....directory-invalidation:1
382 ....opendir:4
384 test_cmp ../trace.expect ../trace.relevant
388 test_expect_success 'verify untracked cache dump' '
389 test-tool dump-untracked-cache >../actual &&
390 cat >../expect <<EOF &&
391 info/exclude $EMPTY_BLOB
392 core.excludesfile $ZERO_OID
393 exclude_per_dir .gitignore
394 flags 00000006
395 / $(test_oid root) recurse valid
396 .gitignore
397 dthree/
398 dtwo/
399 three
400 /done/ $ZERO_OID recurse valid
401 /dthree/ $ZERO_OID recurse check_only valid
402 three
403 /dtwo/ $ZERO_OID recurse check_only valid
406 test_cmp ../expect ../actual
409 test_expect_success 'new info/exclude invalidates everything' '
410 echo three >>.git/info/exclude &&
411 : >../trace.output &&
412 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
413 git status --porcelain >../actual &&
414 iuc status --porcelain >../status.iuc &&
415 cat >../status.expect <<EOF &&
416 A done/one
417 A one
418 A two
419 ?? .gitignore
420 ?? dtwo/
422 test_cmp ../status.expect ../status.iuc &&
423 test_cmp ../status.expect ../actual &&
424 get_relevant_traces ../trace.output ../trace.relevant &&
425 cat >../trace.expect <<EOF &&
426 ....path:
427 ....node-creation:0
428 ....gitignore-invalidation:1
429 ....directory-invalidation:0
430 ....opendir:4
432 test_cmp ../trace.expect ../trace.relevant
435 test_expect_success 'verify untracked cache dump' '
436 test-tool dump-untracked-cache >../actual &&
437 cat >../expect <<EOF &&
438 info/exclude $(test_oid exclude)
439 core.excludesfile $ZERO_OID
440 exclude_per_dir .gitignore
441 flags 00000006
442 / $(test_oid root) recurse valid
443 .gitignore
444 dtwo/
445 /done/ $ZERO_OID recurse valid
446 /dthree/ $ZERO_OID recurse check_only valid
447 /dtwo/ $ZERO_OID recurse check_only valid
450 test_cmp ../expect ../actual
453 test_expect_success 'move two from tracked to untracked' '
454 git rm --cached two &&
455 test-tool dump-untracked-cache >../actual &&
456 cat >../expect <<EOF &&
457 info/exclude $(test_oid exclude)
458 core.excludesfile $ZERO_OID
459 exclude_per_dir .gitignore
460 flags 00000006
461 / $(test_oid root) recurse
462 /done/ $ZERO_OID recurse valid
463 /dthree/ $ZERO_OID recurse check_only valid
464 /dtwo/ $ZERO_OID recurse check_only valid
467 test_cmp ../expect ../actual
470 test_expect_success 'status after the move' '
471 : >../trace.output &&
472 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
473 git status --porcelain >../actual &&
474 iuc status --porcelain >../status.iuc &&
475 cat >../status.expect <<EOF &&
476 A done/one
477 A one
478 ?? .gitignore
479 ?? dtwo/
480 ?? two
482 test_cmp ../status.expect ../status.iuc &&
483 test_cmp ../status.expect ../actual &&
484 get_relevant_traces ../trace.output ../trace.relevant &&
485 cat >../trace.expect <<EOF &&
486 ....path:
487 ....node-creation:0
488 ....gitignore-invalidation:0
489 ....directory-invalidation:0
490 ....opendir:1
492 test_cmp ../trace.expect ../trace.relevant
495 test_expect_success 'verify untracked cache dump' '
496 test-tool dump-untracked-cache >../actual &&
497 cat >../expect <<EOF &&
498 info/exclude $(test_oid exclude)
499 core.excludesfile $ZERO_OID
500 exclude_per_dir .gitignore
501 flags 00000006
502 / $(test_oid root) recurse valid
503 .gitignore
504 dtwo/
506 /done/ $ZERO_OID recurse valid
507 /dthree/ $ZERO_OID recurse check_only valid
508 /dtwo/ $ZERO_OID recurse check_only valid
511 test_cmp ../expect ../actual
514 test_expect_success 'move two from untracked to tracked' '
515 git add two &&
516 test-tool dump-untracked-cache >../actual &&
517 cat >../expect <<EOF &&
518 info/exclude $(test_oid exclude)
519 core.excludesfile $ZERO_OID
520 exclude_per_dir .gitignore
521 flags 00000006
522 / $(test_oid root) recurse
523 /done/ $ZERO_OID recurse valid
524 /dthree/ $ZERO_OID recurse check_only valid
525 /dtwo/ $ZERO_OID recurse check_only valid
528 test_cmp ../expect ../actual
531 test_expect_success 'status after the move' '
532 : >../trace.output &&
533 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
534 git status --porcelain >../actual &&
535 iuc status --porcelain >../status.iuc &&
536 cat >../status.expect <<EOF &&
537 A done/one
538 A one
539 A two
540 ?? .gitignore
541 ?? dtwo/
543 test_cmp ../status.expect ../status.iuc &&
544 test_cmp ../status.expect ../actual &&
545 get_relevant_traces ../trace.output ../trace.relevant &&
546 cat >../trace.expect <<EOF &&
547 ....path:
548 ....node-creation:0
549 ....gitignore-invalidation:0
550 ....directory-invalidation:0
551 ....opendir:1
553 test_cmp ../trace.expect ../trace.relevant
556 test_expect_success 'verify untracked cache dump' '
557 test-tool dump-untracked-cache >../actual &&
558 cat >../expect <<EOF &&
559 info/exclude $(test_oid exclude)
560 core.excludesfile $ZERO_OID
561 exclude_per_dir .gitignore
562 flags 00000006
563 / $(test_oid root) recurse valid
564 .gitignore
565 dtwo/
566 /done/ $ZERO_OID recurse valid
567 /dthree/ $ZERO_OID recurse check_only valid
568 /dtwo/ $ZERO_OID recurse check_only valid
571 test_cmp ../expect ../actual
574 test_expect_success 'set up for sparse checkout testing' '
575 echo two >done/.gitignore &&
576 echo three >>done/.gitignore &&
577 echo two >done/two &&
578 git add -f done/two done/.gitignore &&
579 git commit -m "first commit"
582 test_expect_success 'status after commit' '
583 : >../trace.output &&
584 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
585 git status --porcelain >../actual &&
586 iuc status --porcelain >../status.iuc &&
587 cat >../status.expect <<EOF &&
588 ?? .gitignore
589 ?? dtwo/
591 test_cmp ../status.expect ../status.iuc &&
592 test_cmp ../status.expect ../actual &&
593 get_relevant_traces ../trace.output ../trace.relevant &&
594 cat >../trace.expect <<EOF &&
595 ....path:
596 ....node-creation:0
597 ....gitignore-invalidation:0
598 ....directory-invalidation:0
599 ....opendir:2
601 test_cmp ../trace.expect ../trace.relevant
604 test_expect_success 'untracked cache correct after commit' '
605 test-tool dump-untracked-cache >../actual &&
606 cat >../expect <<EOF &&
607 info/exclude $(test_oid exclude)
608 core.excludesfile $ZERO_OID
609 exclude_per_dir .gitignore
610 flags 00000006
611 / $(test_oid root) recurse valid
612 .gitignore
613 dtwo/
614 /done/ $ZERO_OID recurse valid
615 /dthree/ $ZERO_OID recurse check_only valid
616 /dtwo/ $ZERO_OID recurse check_only valid
619 test_cmp ../expect ../actual
622 test_expect_success 'set up sparse checkout' '
623 echo "done/[a-z]*" >.git/info/sparse-checkout &&
624 test_config core.sparsecheckout true &&
625 git checkout main &&
626 git update-index --force-untracked-cache &&
627 git status --porcelain >/dev/null && # prime the cache
628 test_path_is_missing done/.gitignore &&
629 test_path_is_file done/one
632 test_expect_success 'create/modify files, some of which are gitignored' '
633 echo two bis >done/two &&
634 echo three >done/three && # three is gitignored
635 echo four >done/four && # four is gitignored at a higher level
636 echo five >done/five && # five is not gitignored
637 test-tool chmtime =-180 done/two done/three done/four done/five done &&
638 # we need to ensure that the root dir is touched (in the past);
639 test-tool chmtime =-180 . &&
640 sync_mtime
643 test_expect_success 'test sparse status with untracked cache' '
644 : >../trace.output &&
645 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
646 git status --porcelain >../status.actual &&
647 iuc status --porcelain >../status.iuc &&
648 cat >../status.expect <<EOF &&
649 M done/two
650 ?? .gitignore
651 ?? done/five
652 ?? dtwo/
654 test_cmp ../status.expect ../status.iuc &&
655 test_cmp ../status.expect ../status.actual &&
656 get_relevant_traces ../trace.output ../trace.relevant &&
657 cat >../trace.expect <<EOF &&
658 ....path:
659 ....node-creation:0
660 ....gitignore-invalidation:1
661 ....directory-invalidation:2
662 ....opendir:2
664 test_cmp ../trace.expect ../trace.relevant
667 test_expect_success 'untracked cache correct after status' '
668 test-tool dump-untracked-cache >../actual &&
669 cat >../expect <<EOF &&
670 info/exclude $(test_oid exclude)
671 core.excludesfile $ZERO_OID
672 exclude_per_dir .gitignore
673 flags 00000006
674 / $(test_oid root) recurse valid
675 .gitignore
676 dtwo/
677 /done/ $(test_oid done) recurse valid
678 five
679 /dthree/ $ZERO_OID recurse check_only valid
680 /dtwo/ $ZERO_OID recurse check_only valid
683 test_cmp ../expect ../actual
686 test_expect_success 'test sparse status again with untracked cache' '
687 : >../trace.output &&
688 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
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 ?? dtwo/
697 test_cmp ../status.expect ../status.iuc &&
698 test_cmp ../status.expect ../status.actual &&
699 get_relevant_traces ../trace.output ../trace.relevant &&
700 cat >../trace.expect <<EOF &&
701 ....path:
702 ....node-creation:0
703 ....gitignore-invalidation:0
704 ....directory-invalidation:0
705 ....opendir:0
707 test_cmp ../trace.expect ../trace.relevant
710 test_expect_success 'set up for test of subdir and sparse checkouts' '
711 mkdir done/sub &&
712 mkdir done/sub/sub &&
713 echo "sub" > done/sub/sub/file &&
714 test-tool chmtime =-120 done/sub/sub/file done/sub/sub done/sub done
717 test_expect_success 'test sparse status with untracked cache and subdir' '
718 : >../trace.output &&
719 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
720 git status --porcelain >../status.actual &&
721 iuc status --porcelain >../status.iuc &&
722 cat >../status.expect <<EOF &&
723 M done/two
724 ?? .gitignore
725 ?? done/five
726 ?? done/sub/
727 ?? dtwo/
729 test_cmp ../status.expect ../status.iuc &&
730 test_cmp ../status.expect ../status.actual &&
731 get_relevant_traces ../trace.output ../trace.relevant &&
732 cat >../trace.expect <<EOF &&
733 ....path:
734 ....node-creation:2
735 ....gitignore-invalidation:0
736 ....directory-invalidation:1
737 ....opendir:3
739 test_cmp ../trace.expect ../trace.relevant
742 test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
743 test-tool dump-untracked-cache >../actual &&
744 cat >../expect-from-test-dump <<EOF &&
745 info/exclude $(test_oid exclude)
746 core.excludesfile $ZERO_OID
747 exclude_per_dir .gitignore
748 flags 00000006
749 / $(test_oid root) recurse valid
750 .gitignore
751 dtwo/
752 /done/ $(test_oid done) recurse valid
753 five
754 sub/
755 /done/sub/ $ZERO_OID recurse check_only valid
756 sub/
757 /done/sub/sub/ $ZERO_OID recurse check_only valid
758 file
759 /dthree/ $ZERO_OID recurse check_only valid
760 /dtwo/ $ZERO_OID recurse check_only valid
763 test_cmp ../expect-from-test-dump ../actual
766 test_expect_success 'test sparse status again with untracked cache and subdir' '
767 : >../trace.output &&
768 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
769 git status --porcelain >../status.actual &&
770 iuc status --porcelain >../status.iuc &&
771 test_cmp ../status.expect ../status.iuc &&
772 test_cmp ../status.expect ../status.actual &&
773 get_relevant_traces ../trace.output ../trace.relevant &&
774 cat >../trace.expect <<EOF &&
775 ....path:
776 ....node-creation:0
777 ....gitignore-invalidation:0
778 ....directory-invalidation:0
779 ....opendir:0
781 test_cmp ../trace.expect ../trace.relevant
784 test_expect_success 'move entry in subdir from untracked to cached' '
785 git add dtwo/two &&
786 git status --porcelain >../status.actual &&
787 iuc status --porcelain >../status.iuc &&
788 cat >../status.expect <<EOF &&
789 M done/two
790 A dtwo/two
791 ?? .gitignore
792 ?? done/five
793 ?? done/sub/
795 test_cmp ../status.expect ../status.iuc &&
796 test_cmp ../status.expect ../status.actual
799 test_expect_success 'move entry in subdir from cached to untracked' '
800 git rm --cached dtwo/two &&
801 git status --porcelain >../status.actual &&
802 iuc status --porcelain >../status.iuc &&
803 cat >../status.expect <<EOF &&
804 M done/two
805 ?? .gitignore
806 ?? done/five
807 ?? done/sub/
808 ?? dtwo/
810 test_cmp ../status.expect ../status.iuc &&
811 test_cmp ../status.expect ../status.actual
814 test_expect_success '--no-untracked-cache removes the cache' '
815 git update-index --no-untracked-cache &&
816 test-tool dump-untracked-cache >../actual &&
817 echo "no untracked cache" >../expect-no-uc &&
818 test_cmp ../expect-no-uc ../actual
821 test_expect_success 'git status does not change anything' '
822 git status &&
823 test-tool dump-untracked-cache >../actual &&
824 test_cmp ../expect-no-uc ../actual
827 test_expect_success 'setting core.untrackedCache to true and using git status creates the cache' '
828 git config core.untrackedCache true &&
829 test-tool dump-untracked-cache >../actual &&
830 test_cmp ../expect-no-uc ../actual &&
831 git status &&
832 test-tool dump-untracked-cache >../actual &&
833 test_cmp ../expect-from-test-dump ../actual
836 test_expect_success 'using --no-untracked-cache does not fail when core.untrackedCache is true' '
837 git update-index --no-untracked-cache &&
838 test-tool dump-untracked-cache >../actual &&
839 test_cmp ../expect-no-uc ../actual &&
840 git update-index --untracked-cache &&
841 test-tool dump-untracked-cache >../actual &&
842 test_cmp ../expect-empty ../actual
845 test_expect_success 'setting core.untrackedCache to false and using git status removes the cache' '
846 git config core.untrackedCache false &&
847 test-tool dump-untracked-cache >../actual &&
848 test_cmp ../expect-empty ../actual &&
849 git status &&
850 test-tool dump-untracked-cache >../actual &&
851 test_cmp ../expect-no-uc ../actual
854 test_expect_success 'using --untracked-cache does not fail when core.untrackedCache is false' '
855 git update-index --untracked-cache &&
856 test-tool dump-untracked-cache >../actual &&
857 test_cmp ../expect-empty ../actual
860 test_expect_success 'setting core.untrackedCache to keep' '
861 git config core.untrackedCache keep &&
862 git update-index --untracked-cache &&
863 test-tool dump-untracked-cache >../actual &&
864 test_cmp ../expect-empty ../actual &&
865 git status &&
866 test-tool dump-untracked-cache >../actual &&
867 test_cmp ../expect-from-test-dump ../actual &&
868 git update-index --no-untracked-cache &&
869 test-tool dump-untracked-cache >../actual &&
870 test_cmp ../expect-no-uc ../actual &&
871 git update-index --force-untracked-cache &&
872 test-tool dump-untracked-cache >../actual &&
873 test_cmp ../expect-empty ../actual &&
874 git status &&
875 test-tool dump-untracked-cache >../actual &&
876 test_cmp ../expect-from-test-dump ../actual
879 test_expect_success 'test ident field is working' '
880 mkdir ../other_worktree &&
881 cp -R done dthree dtwo four three ../other_worktree &&
882 GIT_WORK_TREE=../other_worktree git status 2>../err &&
883 echo "warning: untracked cache is disabled on this system or location" >../expect &&
884 test_cmp ../expect ../err
887 test_expect_success 'untracked cache survives a checkout' '
888 git commit --allow-empty -m empty &&
889 test-tool dump-untracked-cache >../before &&
890 test_when_finished "git checkout main" &&
891 git checkout -b other_branch &&
892 test-tool dump-untracked-cache >../after &&
893 test_cmp ../before ../after &&
894 test_commit test &&
895 test-tool dump-untracked-cache >../before &&
896 git checkout main &&
897 test-tool dump-untracked-cache >../after &&
898 test_cmp ../before ../after
901 test_expect_success 'untracked cache survives a commit' '
902 test-tool dump-untracked-cache >../before &&
903 git add done/two &&
904 git commit -m commit &&
905 test-tool dump-untracked-cache >../after &&
906 test_cmp ../before ../after
909 test_expect_success 'teardown worktree' '
910 cd ..
913 test_expect_success SYMLINKS 'setup worktree for symlink test' '
914 git init worktree-symlink &&
915 cd worktree-symlink &&
916 git config core.untrackedCache true &&
917 mkdir one two &&
918 touch one/file two/file &&
919 git add one/file two/file &&
920 git commit -m"first commit" &&
921 git rm -rf one &&
922 ln -s two one &&
923 git add one &&
924 git commit -m"second commit"
927 test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=true' '
928 git checkout HEAD~ &&
929 status_is_clean &&
930 status_is_clean &&
931 git checkout main &&
932 avoid_racy &&
933 status_is_clean &&
934 status_is_clean
937 test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=false' '
938 git config core.untrackedCache false &&
939 git checkout HEAD~ &&
940 status_is_clean &&
941 status_is_clean &&
942 git checkout main &&
943 avoid_racy &&
944 status_is_clean &&
945 status_is_clean
948 test_expect_success 'setup worktree for non-symlink test' '
949 git init worktree-non-symlink &&
950 cd worktree-non-symlink &&
951 git config core.untrackedCache true &&
952 mkdir one two &&
953 touch one/file two/file &&
954 git add one/file two/file &&
955 git commit -m"first commit" &&
956 git rm -rf one &&
957 cp two/file one &&
958 git add one &&
959 git commit -m"second commit"
962 test_expect_success '"status" after file replacement should be clean with UC=true' '
963 git checkout HEAD~ &&
964 status_is_clean &&
965 status_is_clean &&
966 git checkout main &&
967 avoid_racy &&
968 status_is_clean &&
969 test-tool dump-untracked-cache >../actual &&
970 grep -F "recurse valid" ../actual >../actual.grep &&
971 cat >../expect.grep <<EOF &&
972 / $ZERO_OID recurse valid
973 /two/ $ZERO_OID recurse valid
975 status_is_clean &&
976 test_cmp ../expect.grep ../actual.grep
979 test_expect_success '"status" after file replacement should be clean with UC=false' '
980 git config core.untrackedCache false &&
981 git checkout HEAD~ &&
982 status_is_clean &&
983 status_is_clean &&
984 git checkout main &&
985 avoid_racy &&
986 status_is_clean &&
987 status_is_clean
990 test_expect_success 'empty repo (no index) and core.untrackedCache' '
991 git init emptyrepo &&
992 git -C emptyrepo -c core.untrackedCache=true write-tree
995 test_done