]> git.ipfire.org Git - thirdparty/git.git/blob - t/t7063-status-untracked-cache.sh
clone: allow "--bare" with "-o"
[thirdparty/git.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 test-tool chmtime =-300 one two three done/one dtwo/two dthree/three &&
94 test-tool chmtime =-300 done dtwo dthree &&
95 test-tool chmtime =-300 . &&
96 git add one two done/one &&
97 : >.git/info/exclude &&
98 git update-index --untracked-cache &&
99 test_oid_cache <<-EOF
100 root sha1:e6fcc8f2ee31bae321d66afd183fcb7237afae6e
101 root sha256:b90c672088c015b9c83876e919da311bad4cd39639fb139f988af6a11493b974
102
103 exclude sha1:13263c0978fb9fad16b2d580fb800b6d811c3ff0
104 exclude sha256:fe4aaa1bbbbce4cb8f73426748a14c5ad6026b26f90505a0bf2494b165a5b76c
105
106 done sha1:1946f0437f90c5005533cbe1736a6451ca301714
107 done sha256:7f079501d79f665b3acc50f5e0e9e94509084d5032ac20113a37dd5029b757cc
108 EOF
109 '
110
111 test_expect_success 'untracked cache is empty' '
112 test-tool dump-untracked-cache >../actual &&
113 cat >../expect-empty <<EOF &&
114 info/exclude $ZERO_OID
115 core.excludesfile $ZERO_OID
116 exclude_per_dir .gitignore
117 flags 00000006
118 EOF
119 test_cmp ../expect-empty ../actual
120 '
121
122 cat >../status.expect <<EOF &&
123 A done/one
124 A one
125 A two
126 ?? dthree/
127 ?? dtwo/
128 ?? three
129 EOF
130
131 cat >../dump.expect <<EOF &&
132 info/exclude $EMPTY_BLOB
133 core.excludesfile $ZERO_OID
134 exclude_per_dir .gitignore
135 flags 00000006
136 / $ZERO_OID recurse valid
137 dthree/
138 dtwo/
139 three
140 /done/ $ZERO_OID recurse valid
141 /dthree/ $ZERO_OID recurse check_only valid
142 three
143 /dtwo/ $ZERO_OID recurse check_only valid
144 two
145 EOF
146
147 test_expect_success 'status first time (empty cache)' '
148 : >../trace.output &&
149 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
150 git status --porcelain >../actual &&
151 iuc status --porcelain >../status.iuc &&
152 test_cmp ../status.expect ../status.iuc &&
153 test_cmp ../status.expect ../actual &&
154 get_relevant_traces ../trace.output ../trace.relevant &&
155 cat >../trace.expect <<EOF &&
156 ....path:
157 ....node-creation:3
158 ....gitignore-invalidation:1
159 ....directory-invalidation:0
160 ....opendir:4
161 EOF
162 test_cmp ../trace.expect ../trace.relevant
163 '
164
165 test_expect_success 'untracked cache after first status' '
166 test-tool dump-untracked-cache >../actual &&
167 test_cmp ../dump.expect ../actual
168 '
169
170 test_expect_success 'status second time (fully populated cache)' '
171 : >../trace.output &&
172 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
173 git status --porcelain >../actual &&
174 iuc status --porcelain >../status.iuc &&
175 test_cmp ../status.expect ../status.iuc &&
176 test_cmp ../status.expect ../actual &&
177 get_relevant_traces ../trace.output ../trace.relevant &&
178 cat >../trace.expect <<EOF &&
179 ....path:
180 ....node-creation:0
181 ....gitignore-invalidation:0
182 ....directory-invalidation:0
183 ....opendir:0
184 EOF
185 test_cmp ../trace.expect ../trace.relevant
186 '
187
188 test_expect_success 'untracked cache after second status' '
189 test-tool dump-untracked-cache >../actual &&
190 test_cmp ../dump.expect ../actual
191 '
192
193 cat >../status_uall.expect <<EOF &&
194 A done/one
195 A one
196 A two
197 ?? dthree/three
198 ?? dtwo/two
199 ?? three
200 EOF
201
202 # Bypassing the untracked cache here is not desirable from an
203 # end-user perspective, but is expected in the current design.
204 # The untracked cache data stored for a -unormal run cannot be
205 # correctly used in a -uall run - it would yield incorrect output.
206 test_expect_success 'untracked cache is bypassed with -uall' '
207 : >../trace.output &&
208 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
209 git status -uall --porcelain >../actual &&
210 iuc status -uall --porcelain >../status.iuc &&
211 test_cmp ../status_uall.expect ../status.iuc &&
212 test_cmp ../status_uall.expect ../actual &&
213 get_relevant_traces ../trace.output ../trace.relevant &&
214 cat >../trace.expect <<EOF &&
215 ....path:
216 EOF
217 test_cmp ../trace.expect ../trace.relevant
218 '
219
220 test_expect_success 'untracked cache remains after bypass' '
221 test-tool dump-untracked-cache >../actual &&
222 test_cmp ../dump.expect ../actual
223 '
224
225 test_expect_success 'if -uall is configured, untracked cache gets populated by default' '
226 test_config status.showuntrackedfiles all &&
227 : >../trace.output &&
228 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
229 git status --porcelain >../actual &&
230 iuc status --porcelain >../status.iuc &&
231 test_cmp ../status_uall.expect ../status.iuc &&
232 test_cmp ../status_uall.expect ../actual &&
233 get_relevant_traces ../trace.output ../trace.relevant &&
234 cat >../trace.expect <<EOF &&
235 ....path:
236 ....node-creation:3
237 ....gitignore-invalidation:1
238 ....directory-invalidation:0
239 ....opendir:4
240 EOF
241 test_cmp ../trace.expect ../trace.relevant
242 '
243
244 cat >../dump_uall.expect <<EOF &&
245 info/exclude $EMPTY_BLOB
246 core.excludesfile $ZERO_OID
247 exclude_per_dir .gitignore
248 flags 00000000
249 / $ZERO_OID recurse valid
250 three
251 /done/ $ZERO_OID recurse valid
252 /dthree/ $ZERO_OID recurse valid
253 three
254 /dtwo/ $ZERO_OID recurse valid
255 two
256 EOF
257
258 test_expect_success 'if -uall was configured, untracked cache is populated' '
259 test-tool dump-untracked-cache >../actual &&
260 test_cmp ../dump_uall.expect ../actual
261 '
262
263 test_expect_success 'if -uall is configured, untracked cache is used by default' '
264 test_config status.showuntrackedfiles all &&
265 : >../trace.output &&
266 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
267 git status --porcelain >../actual &&
268 iuc status --porcelain >../status.iuc &&
269 test_cmp ../status_uall.expect ../status.iuc &&
270 test_cmp ../status_uall.expect ../actual &&
271 get_relevant_traces ../trace.output ../trace.relevant &&
272 cat >../trace.expect <<EOF &&
273 ....path:
274 ....node-creation:0
275 ....gitignore-invalidation:0
276 ....directory-invalidation:0
277 ....opendir:0
278 EOF
279 test_cmp ../trace.expect ../trace.relevant
280 '
281
282 # Bypassing the untracked cache here is not desirable from an
283 # end-user perspective, but is expected in the current design.
284 # The untracked cache data stored for a -all run cannot be
285 # correctly used in a -unormal run - it would yield incorrect
286 # output.
287 test_expect_success 'if -uall is configured, untracked cache is bypassed with -unormal' '
288 test_config status.showuntrackedfiles all &&
289 : >../trace.output &&
290 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
291 git status -unormal --porcelain >../actual &&
292 iuc status -unormal --porcelain >../status.iuc &&
293 test_cmp ../status.expect ../status.iuc &&
294 test_cmp ../status.expect ../actual &&
295 get_relevant_traces ../trace.output ../trace.relevant &&
296 cat >../trace.expect <<EOF &&
297 ....path:
298 EOF
299 test_cmp ../trace.expect ../trace.relevant
300 '
301
302 test_expect_success 'repopulate untracked cache for -unormal' '
303 git status --porcelain
304 '
305
306 test_expect_success 'modify in root directory, one dir invalidation' '
307 : >four &&
308 test-tool chmtime =-240 four &&
309 : >../trace.output &&
310 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
311 git status --porcelain >../actual &&
312 iuc status --porcelain >../status.iuc &&
313 cat >../status.expect <<EOF &&
314 A done/one
315 A one
316 A two
317 ?? dthree/
318 ?? dtwo/
319 ?? four
320 ?? three
321 EOF
322 test_cmp ../status.expect ../status.iuc &&
323 test_cmp ../status.expect ../actual &&
324 get_relevant_traces ../trace.output ../trace.relevant &&
325 cat >../trace.expect <<EOF &&
326 ....path:
327 ....node-creation:0
328 ....gitignore-invalidation:0
329 ....directory-invalidation:1
330 ....opendir:1
331 EOF
332 test_cmp ../trace.expect ../trace.relevant
333
334 '
335
336 test_expect_success 'verify untracked cache dump' '
337 test-tool dump-untracked-cache >../actual &&
338 cat >../expect <<EOF &&
339 info/exclude $EMPTY_BLOB
340 core.excludesfile $ZERO_OID
341 exclude_per_dir .gitignore
342 flags 00000006
343 / $ZERO_OID recurse valid
344 dthree/
345 dtwo/
346 four
347 three
348 /done/ $ZERO_OID recurse valid
349 /dthree/ $ZERO_OID recurse check_only valid
350 three
351 /dtwo/ $ZERO_OID recurse check_only valid
352 two
353 EOF
354 test_cmp ../expect ../actual
355 '
356
357 test_expect_success 'new .gitignore invalidates recursively' '
358 echo four >.gitignore &&
359 : >../trace.output &&
360 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
361 git status --porcelain >../actual &&
362 iuc status --porcelain >../status.iuc &&
363 cat >../status.expect <<EOF &&
364 A done/one
365 A one
366 A two
367 ?? .gitignore
368 ?? dthree/
369 ?? dtwo/
370 ?? three
371 EOF
372 test_cmp ../status.expect ../status.iuc &&
373 test_cmp ../status.expect ../actual &&
374 get_relevant_traces ../trace.output ../trace.relevant &&
375 cat >../trace.expect <<EOF &&
376 ....path:
377 ....node-creation:0
378 ....gitignore-invalidation:1
379 ....directory-invalidation:1
380 ....opendir:4
381 EOF
382 test_cmp ../trace.expect ../trace.relevant
383
384 '
385
386 test_expect_success 'verify untracked cache dump' '
387 test-tool dump-untracked-cache >../actual &&
388 cat >../expect <<EOF &&
389 info/exclude $EMPTY_BLOB
390 core.excludesfile $ZERO_OID
391 exclude_per_dir .gitignore
392 flags 00000006
393 / $(test_oid root) recurse valid
394 .gitignore
395 dthree/
396 dtwo/
397 three
398 /done/ $ZERO_OID recurse valid
399 /dthree/ $ZERO_OID recurse check_only valid
400 three
401 /dtwo/ $ZERO_OID recurse check_only valid
402 two
403 EOF
404 test_cmp ../expect ../actual
405 '
406
407 test_expect_success 'new info/exclude invalidates everything' '
408 echo three >>.git/info/exclude &&
409 : >../trace.output &&
410 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
411 git status --porcelain >../actual &&
412 iuc status --porcelain >../status.iuc &&
413 cat >../status.expect <<EOF &&
414 A done/one
415 A one
416 A two
417 ?? .gitignore
418 ?? dtwo/
419 EOF
420 test_cmp ../status.expect ../status.iuc &&
421 test_cmp ../status.expect ../actual &&
422 get_relevant_traces ../trace.output ../trace.relevant &&
423 cat >../trace.expect <<EOF &&
424 ....path:
425 ....node-creation:0
426 ....gitignore-invalidation:1
427 ....directory-invalidation:0
428 ....opendir:4
429 EOF
430 test_cmp ../trace.expect ../trace.relevant
431 '
432
433 test_expect_success 'verify untracked cache dump' '
434 test-tool dump-untracked-cache >../actual &&
435 cat >../expect <<EOF &&
436 info/exclude $(test_oid exclude)
437 core.excludesfile $ZERO_OID
438 exclude_per_dir .gitignore
439 flags 00000006
440 / $(test_oid root) recurse valid
441 .gitignore
442 dtwo/
443 /done/ $ZERO_OID recurse valid
444 /dthree/ $ZERO_OID recurse check_only valid
445 /dtwo/ $ZERO_OID recurse check_only valid
446 two
447 EOF
448 test_cmp ../expect ../actual
449 '
450
451 test_expect_success 'move two from tracked to untracked' '
452 git rm --cached two &&
453 test-tool dump-untracked-cache >../actual &&
454 cat >../expect <<EOF &&
455 info/exclude $(test_oid exclude)
456 core.excludesfile $ZERO_OID
457 exclude_per_dir .gitignore
458 flags 00000006
459 / $(test_oid root) recurse
460 /done/ $ZERO_OID recurse valid
461 /dthree/ $ZERO_OID recurse check_only valid
462 /dtwo/ $ZERO_OID recurse check_only valid
463 two
464 EOF
465 test_cmp ../expect ../actual
466 '
467
468 test_expect_success 'status after the move' '
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 A done/one
475 A one
476 ?? .gitignore
477 ?? dtwo/
478 ?? two
479 EOF
480 test_cmp ../status.expect ../status.iuc &&
481 test_cmp ../status.expect ../actual &&
482 get_relevant_traces ../trace.output ../trace.relevant &&
483 cat >../trace.expect <<EOF &&
484 ....path:
485 ....node-creation:0
486 ....gitignore-invalidation:0
487 ....directory-invalidation:0
488 ....opendir:1
489 EOF
490 test_cmp ../trace.expect ../trace.relevant
491 '
492
493 test_expect_success 'verify untracked cache dump' '
494 test-tool dump-untracked-cache >../actual &&
495 cat >../expect <<EOF &&
496 info/exclude $(test_oid exclude)
497 core.excludesfile $ZERO_OID
498 exclude_per_dir .gitignore
499 flags 00000006
500 / $(test_oid root) recurse valid
501 .gitignore
502 dtwo/
503 two
504 /done/ $ZERO_OID recurse valid
505 /dthree/ $ZERO_OID recurse check_only valid
506 /dtwo/ $ZERO_OID recurse check_only valid
507 two
508 EOF
509 test_cmp ../expect ../actual
510 '
511
512 test_expect_success 'move two from untracked to tracked' '
513 git add two &&
514 test-tool dump-untracked-cache >../actual &&
515 cat >../expect <<EOF &&
516 info/exclude $(test_oid exclude)
517 core.excludesfile $ZERO_OID
518 exclude_per_dir .gitignore
519 flags 00000006
520 / $(test_oid root) recurse
521 /done/ $ZERO_OID recurse valid
522 /dthree/ $ZERO_OID recurse check_only valid
523 /dtwo/ $ZERO_OID recurse check_only valid
524 two
525 EOF
526 test_cmp ../expect ../actual
527 '
528
529 test_expect_success 'status after the move' '
530 : >../trace.output &&
531 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
532 git status --porcelain >../actual &&
533 iuc status --porcelain >../status.iuc &&
534 cat >../status.expect <<EOF &&
535 A done/one
536 A one
537 A two
538 ?? .gitignore
539 ?? dtwo/
540 EOF
541 test_cmp ../status.expect ../status.iuc &&
542 test_cmp ../status.expect ../actual &&
543 get_relevant_traces ../trace.output ../trace.relevant &&
544 cat >../trace.expect <<EOF &&
545 ....path:
546 ....node-creation:0
547 ....gitignore-invalidation:0
548 ....directory-invalidation:0
549 ....opendir:1
550 EOF
551 test_cmp ../trace.expect ../trace.relevant
552 '
553
554 test_expect_success 'verify untracked cache dump' '
555 test-tool dump-untracked-cache >../actual &&
556 cat >../expect <<EOF &&
557 info/exclude $(test_oid exclude)
558 core.excludesfile $ZERO_OID
559 exclude_per_dir .gitignore
560 flags 00000006
561 / $(test_oid root) recurse valid
562 .gitignore
563 dtwo/
564 /done/ $ZERO_OID recurse valid
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 'set up for sparse checkout testing' '
573 echo two >done/.gitignore &&
574 echo three >>done/.gitignore &&
575 echo two >done/two &&
576 git add -f done/two done/.gitignore &&
577 git commit -m "first commit"
578 '
579
580 test_expect_success 'status after commit' '
581 : >../trace.output &&
582 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
583 git status --porcelain >../actual &&
584 iuc status --porcelain >../status.iuc &&
585 cat >../status.expect <<EOF &&
586 ?? .gitignore
587 ?? dtwo/
588 EOF
589 test_cmp ../status.expect ../status.iuc &&
590 test_cmp ../status.expect ../actual &&
591 get_relevant_traces ../trace.output ../trace.relevant &&
592 cat >../trace.expect <<EOF &&
593 ....path:
594 ....node-creation:0
595 ....gitignore-invalidation:0
596 ....directory-invalidation:0
597 ....opendir:2
598 EOF
599 test_cmp ../trace.expect ../trace.relevant
600 '
601
602 test_expect_success 'untracked cache correct after commit' '
603 test-tool dump-untracked-cache >../actual &&
604 cat >../expect <<EOF &&
605 info/exclude $(test_oid exclude)
606 core.excludesfile $ZERO_OID
607 exclude_per_dir .gitignore
608 flags 00000006
609 / $(test_oid root) recurse valid
610 .gitignore
611 dtwo/
612 /done/ $ZERO_OID recurse valid
613 /dthree/ $ZERO_OID recurse check_only valid
614 /dtwo/ $ZERO_OID recurse check_only valid
615 two
616 EOF
617 test_cmp ../expect ../actual
618 '
619
620 test_expect_success 'set up sparse checkout' '
621 echo "done/[a-z]*" >.git/info/sparse-checkout &&
622 test_config core.sparsecheckout true &&
623 git checkout main &&
624 git update-index --force-untracked-cache &&
625 git status --porcelain >/dev/null && # prime the cache
626 test_path_is_missing done/.gitignore &&
627 test_path_is_file done/one
628 '
629
630 test_expect_success 'create/modify files, some of which are gitignored' '
631 echo two bis >done/two &&
632 echo three >done/three && # three is gitignored
633 echo four >done/four && # four is gitignored at a higher level
634 echo five >done/five && # five is not gitignored
635 test-tool chmtime =-180 done/two done/three done/four done/five done &&
636 # we need to ensure that the root dir is touched (in the past);
637 test-tool chmtime =-180 . &&
638 sync_mtime
639 '
640
641 test_expect_success 'test sparse status with untracked cache' '
642 : >../trace.output &&
643 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
644 git status --porcelain >../status.actual &&
645 iuc status --porcelain >../status.iuc &&
646 cat >../status.expect <<EOF &&
647 M done/two
648 ?? .gitignore
649 ?? done/five
650 ?? dtwo/
651 EOF
652 test_cmp ../status.expect ../status.iuc &&
653 test_cmp ../status.expect ../status.actual &&
654 get_relevant_traces ../trace.output ../trace.relevant &&
655 cat >../trace.expect <<EOF &&
656 ....path:
657 ....node-creation:0
658 ....gitignore-invalidation:1
659 ....directory-invalidation:2
660 ....opendir:2
661 EOF
662 test_cmp ../trace.expect ../trace.relevant
663 '
664
665 test_expect_success 'untracked cache correct after status' '
666 test-tool dump-untracked-cache >../actual &&
667 cat >../expect <<EOF &&
668 info/exclude $(test_oid exclude)
669 core.excludesfile $ZERO_OID
670 exclude_per_dir .gitignore
671 flags 00000006
672 / $(test_oid root) recurse valid
673 .gitignore
674 dtwo/
675 /done/ $(test_oid done) recurse valid
676 five
677 /dthree/ $ZERO_OID recurse check_only valid
678 /dtwo/ $ZERO_OID recurse check_only valid
679 two
680 EOF
681 test_cmp ../expect ../actual
682 '
683
684 test_expect_success 'test sparse status again with untracked cache' '
685 : >../trace.output &&
686 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
687 git status --porcelain >../status.actual &&
688 iuc status --porcelain >../status.iuc &&
689 cat >../status.expect <<EOF &&
690 M done/two
691 ?? .gitignore
692 ?? done/five
693 ?? dtwo/
694 EOF
695 test_cmp ../status.expect ../status.iuc &&
696 test_cmp ../status.expect ../status.actual &&
697 get_relevant_traces ../trace.output ../trace.relevant &&
698 cat >../trace.expect <<EOF &&
699 ....path:
700 ....node-creation:0
701 ....gitignore-invalidation:0
702 ....directory-invalidation:0
703 ....opendir:0
704 EOF
705 test_cmp ../trace.expect ../trace.relevant
706 '
707
708 test_expect_success 'set up for test of subdir and sparse checkouts' '
709 mkdir done/sub &&
710 mkdir done/sub/sub &&
711 echo "sub" > done/sub/sub/file &&
712 test-tool chmtime =-120 done/sub/sub/file done/sub/sub done/sub done
713 '
714
715 test_expect_success 'test sparse status with untracked cache and subdir' '
716 : >../trace.output &&
717 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
718 git status --porcelain >../status.actual &&
719 iuc status --porcelain >../status.iuc &&
720 cat >../status.expect <<EOF &&
721 M done/two
722 ?? .gitignore
723 ?? done/five
724 ?? done/sub/
725 ?? dtwo/
726 EOF
727 test_cmp ../status.expect ../status.iuc &&
728 test_cmp ../status.expect ../status.actual &&
729 get_relevant_traces ../trace.output ../trace.relevant &&
730 cat >../trace.expect <<EOF &&
731 ....path:
732 ....node-creation:2
733 ....gitignore-invalidation:0
734 ....directory-invalidation:1
735 ....opendir:3
736 EOF
737 test_cmp ../trace.expect ../trace.relevant
738 '
739
740 test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
741 test-tool dump-untracked-cache >../actual &&
742 cat >../expect-from-test-dump <<EOF &&
743 info/exclude $(test_oid exclude)
744 core.excludesfile $ZERO_OID
745 exclude_per_dir .gitignore
746 flags 00000006
747 / $(test_oid root) recurse valid
748 .gitignore
749 dtwo/
750 /done/ $(test_oid done) recurse valid
751 five
752 sub/
753 /done/sub/ $ZERO_OID recurse check_only valid
754 sub/
755 /done/sub/sub/ $ZERO_OID recurse check_only valid
756 file
757 /dthree/ $ZERO_OID recurse check_only valid
758 /dtwo/ $ZERO_OID recurse check_only valid
759 two
760 EOF
761 test_cmp ../expect-from-test-dump ../actual
762 '
763
764 test_expect_success 'test sparse status again with untracked cache and subdir' '
765 : >../trace.output &&
766 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
767 git status --porcelain >../status.actual &&
768 iuc status --porcelain >../status.iuc &&
769 test_cmp ../status.expect ../status.iuc &&
770 test_cmp ../status.expect ../status.actual &&
771 get_relevant_traces ../trace.output ../trace.relevant &&
772 cat >../trace.expect <<EOF &&
773 ....path:
774 ....node-creation:0
775 ....gitignore-invalidation:0
776 ....directory-invalidation:0
777 ....opendir:0
778 EOF
779 test_cmp ../trace.expect ../trace.relevant
780 '
781
782 test_expect_success 'move entry in subdir from untracked to cached' '
783 git add dtwo/two &&
784 git status --porcelain >../status.actual &&
785 iuc status --porcelain >../status.iuc &&
786 cat >../status.expect <<EOF &&
787 M done/two
788 A dtwo/two
789 ?? .gitignore
790 ?? done/five
791 ?? done/sub/
792 EOF
793 test_cmp ../status.expect ../status.iuc &&
794 test_cmp ../status.expect ../status.actual
795 '
796
797 test_expect_success 'move entry in subdir from cached to untracked' '
798 git rm --cached dtwo/two &&
799 git status --porcelain >../status.actual &&
800 iuc status --porcelain >../status.iuc &&
801 cat >../status.expect <<EOF &&
802 M done/two
803 ?? .gitignore
804 ?? done/five
805 ?? done/sub/
806 ?? dtwo/
807 EOF
808 test_cmp ../status.expect ../status.iuc &&
809 test_cmp ../status.expect ../status.actual
810 '
811
812 test_expect_success '--no-untracked-cache removes the cache' '
813 git update-index --no-untracked-cache &&
814 test-tool dump-untracked-cache >../actual &&
815 echo "no untracked cache" >../expect-no-uc &&
816 test_cmp ../expect-no-uc ../actual
817 '
818
819 test_expect_success 'git status does not change anything' '
820 git status &&
821 test-tool dump-untracked-cache >../actual &&
822 test_cmp ../expect-no-uc ../actual
823 '
824
825 test_expect_success 'setting core.untrackedCache to true and using git status creates the cache' '
826 git config core.untrackedCache true &&
827 test-tool dump-untracked-cache >../actual &&
828 test_cmp ../expect-no-uc ../actual &&
829 git status &&
830 test-tool dump-untracked-cache >../actual &&
831 test_cmp ../expect-from-test-dump ../actual
832 '
833
834 test_expect_success 'using --no-untracked-cache does not fail when core.untrackedCache is true' '
835 git update-index --no-untracked-cache &&
836 test-tool dump-untracked-cache >../actual &&
837 test_cmp ../expect-no-uc ../actual &&
838 git update-index --untracked-cache &&
839 test-tool dump-untracked-cache >../actual &&
840 test_cmp ../expect-empty ../actual
841 '
842
843 test_expect_success 'setting core.untrackedCache to false and using git status removes the cache' '
844 git config core.untrackedCache false &&
845 test-tool dump-untracked-cache >../actual &&
846 test_cmp ../expect-empty ../actual &&
847 git status &&
848 test-tool dump-untracked-cache >../actual &&
849 test_cmp ../expect-no-uc ../actual
850 '
851
852 test_expect_success 'using --untracked-cache does not fail when core.untrackedCache is false' '
853 git update-index --untracked-cache &&
854 test-tool dump-untracked-cache >../actual &&
855 test_cmp ../expect-empty ../actual
856 '
857
858 test_expect_success 'setting core.untrackedCache to keep' '
859 git config core.untrackedCache keep &&
860 git update-index --untracked-cache &&
861 test-tool dump-untracked-cache >../actual &&
862 test_cmp ../expect-empty ../actual &&
863 git status &&
864 test-tool dump-untracked-cache >../actual &&
865 test_cmp ../expect-from-test-dump ../actual &&
866 git update-index --no-untracked-cache &&
867 test-tool dump-untracked-cache >../actual &&
868 test_cmp ../expect-no-uc ../actual &&
869 git update-index --force-untracked-cache &&
870 test-tool dump-untracked-cache >../actual &&
871 test_cmp ../expect-empty ../actual &&
872 git status &&
873 test-tool dump-untracked-cache >../actual &&
874 test_cmp ../expect-from-test-dump ../actual
875 '
876
877 test_expect_success 'test ident field is working' '
878 mkdir ../other_worktree &&
879 cp -R done dthree dtwo four three ../other_worktree &&
880 GIT_WORK_TREE=../other_worktree git status 2>../err &&
881 echo "warning: untracked cache is disabled on this system or location" >../expect &&
882 test_cmp ../expect ../err
883 '
884
885 test_expect_success 'untracked cache survives a checkout' '
886 git commit --allow-empty -m empty &&
887 test-tool dump-untracked-cache >../before &&
888 test_when_finished "git checkout main" &&
889 git checkout -b other_branch &&
890 test-tool dump-untracked-cache >../after &&
891 test_cmp ../before ../after &&
892 test_commit test &&
893 test-tool dump-untracked-cache >../before &&
894 git checkout main &&
895 test-tool dump-untracked-cache >../after &&
896 test_cmp ../before ../after
897 '
898
899 test_expect_success 'untracked cache survives a commit' '
900 test-tool dump-untracked-cache >../before &&
901 git add done/two &&
902 git commit -m commit &&
903 test-tool dump-untracked-cache >../after &&
904 test_cmp ../before ../after
905 '
906
907 test_expect_success 'teardown worktree' '
908 cd ..
909 '
910
911 test_expect_success SYMLINKS 'setup worktree for symlink test' '
912 git init worktree-symlink &&
913 cd worktree-symlink &&
914 git config core.untrackedCache true &&
915 mkdir one two &&
916 touch one/file two/file &&
917 git add one/file two/file &&
918 git commit -m"first commit" &&
919 git rm -rf one &&
920 ln -s two one &&
921 git add one &&
922 git commit -m"second commit"
923 '
924
925 test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=true' '
926 git checkout HEAD~ &&
927 status_is_clean &&
928 status_is_clean &&
929 git checkout main &&
930 avoid_racy &&
931 status_is_clean &&
932 status_is_clean
933 '
934
935 test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=false' '
936 git config core.untrackedCache false &&
937 git checkout HEAD~ &&
938 status_is_clean &&
939 status_is_clean &&
940 git checkout main &&
941 avoid_racy &&
942 status_is_clean &&
943 status_is_clean
944 '
945
946 test_expect_success 'setup worktree for non-symlink test' '
947 git init worktree-non-symlink &&
948 cd worktree-non-symlink &&
949 git config core.untrackedCache true &&
950 mkdir one two &&
951 touch one/file two/file &&
952 git add one/file two/file &&
953 git commit -m"first commit" &&
954 git rm -rf one &&
955 cp two/file one &&
956 git add one &&
957 git commit -m"second commit"
958 '
959
960 test_expect_success '"status" after file replacement should be clean with UC=true' '
961 git checkout HEAD~ &&
962 status_is_clean &&
963 status_is_clean &&
964 git checkout main &&
965 avoid_racy &&
966 status_is_clean &&
967 test-tool dump-untracked-cache >../actual &&
968 grep -F "recurse valid" ../actual >../actual.grep &&
969 cat >../expect.grep <<EOF &&
970 / $ZERO_OID recurse valid
971 /two/ $ZERO_OID recurse valid
972 EOF
973 status_is_clean &&
974 test_cmp ../expect.grep ../actual.grep
975 '
976
977 test_expect_success '"status" after file replacement should be clean with UC=false' '
978 git config core.untrackedCache false &&
979 git checkout HEAD~ &&
980 status_is_clean &&
981 status_is_clean &&
982 git checkout main &&
983 avoid_racy &&
984 status_is_clean &&
985 status_is_clean
986 '
987
988 test_expect_success 'empty repo (no index) and core.untrackedCache' '
989 git init emptyrepo &&
990 git -C emptyrepo -c core.untrackedCache=true write-tree
991 '
992
993 test_done