3 test_description='test untracked cache'
7 # On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
8 # is updated lazily after contents in the directory changes, which
9 # forces the untracked cache code to take the slow path. A test
10 # that wants to make sure that the fast path works correctly should
11 # call this helper to make mtime of the containing directory in sync
12 # with the reality before checking the fast path behaviour.
14 # See <20160803174522.5571-1-pclouds@gmail.com> if you want to know
18 find . -type d -ls >/dev/null
25 test_lazy_prereq UNTRACKED_CACHE '
26 { git update-index --test-untracked-cache; ret=$?; } &&
30 if ! test_have_prereq UNTRACKED_CACHE; then
31 skip_all='This system does not support untracked cache'
35 test_expect_success 'core.untrackedCache is unset' '
36 test_must_fail git config --get core.untrackedCache
39 test_expect_success 'setup' '
42 mkdir done dtwo dthree &&
43 touch one two three done/one dtwo/two dthree/three &&
44 git add one two done/one &&
45 : >.git/info/exclude &&
46 git update-index --untracked-cache
49 test_expect_success 'untracked cache is empty' '
50 test-dump-untracked-cache >../actual &&
51 cat >../expect-empty <<EOF &&
52 info/exclude 0000000000000000000000000000000000000000
53 core.excludesfile 0000000000000000000000000000000000000000
54 exclude_per_dir .gitignore
57 test_cmp ../expect-empty ../actual
60 cat >../status.expect <<EOF &&
69 cat >../dump.expect <<EOF &&
70 info/exclude $EMPTY_BLOB
71 core.excludesfile 0000000000000000000000000000000000000000
72 exclude_per_dir .gitignore
74 / 0000000000000000000000000000000000000000 recurse valid
78 /done/ 0000000000000000000000000000000000000000 recurse valid
79 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
81 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
85 test_expect_success 'status first time (empty cache)' '
88 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
89 git status --porcelain >../actual &&
90 test_cmp ../status.expect ../actual &&
91 cat >../trace.expect <<EOF &&
93 gitignore invalidation: 1
94 directory invalidation: 0
97 test_cmp ../trace.expect ../trace
100 test_expect_success 'untracked cache after first status' '
101 test-dump-untracked-cache >../actual &&
102 test_cmp ../dump.expect ../actual
105 test_expect_success 'status second time (fully populated cache)' '
108 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
109 git status --porcelain >../actual &&
110 test_cmp ../status.expect ../actual &&
111 cat >../trace.expect <<EOF &&
113 gitignore invalidation: 0
114 directory invalidation: 0
117 test_cmp ../trace.expect ../trace
120 test_expect_success 'untracked cache after second status' '
121 test-dump-untracked-cache >../actual &&
122 test_cmp ../dump.expect ../actual
125 test_expect_success 'modify in root directory, one dir invalidation' '
129 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
130 git status --porcelain >../actual &&
131 cat >../status.expect <<EOF &&
140 test_cmp ../status.expect ../actual &&
141 cat >../trace.expect <<EOF &&
143 gitignore invalidation: 0
144 directory invalidation: 1
147 test_cmp ../trace.expect ../trace
151 test_expect_success 'verify untracked cache dump' '
152 test-dump-untracked-cache >../actual &&
153 cat >../expect <<EOF &&
154 info/exclude $EMPTY_BLOB
155 core.excludesfile 0000000000000000000000000000000000000000
156 exclude_per_dir .gitignore
158 / 0000000000000000000000000000000000000000 recurse valid
163 /done/ 0000000000000000000000000000000000000000 recurse valid
164 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
166 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
169 test_cmp ../expect ../actual
172 test_expect_success 'new .gitignore invalidates recursively' '
174 echo four >.gitignore &&
176 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
177 git status --porcelain >../actual &&
178 cat >../status.expect <<EOF &&
187 test_cmp ../status.expect ../actual &&
188 cat >../trace.expect <<EOF &&
190 gitignore invalidation: 1
191 directory invalidation: 1
194 test_cmp ../trace.expect ../trace
198 test_expect_success 'verify untracked cache dump' '
199 test-dump-untracked-cache >../actual &&
200 cat >../expect <<EOF &&
201 info/exclude $EMPTY_BLOB
202 core.excludesfile 0000000000000000000000000000000000000000
203 exclude_per_dir .gitignore
205 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
210 /done/ 0000000000000000000000000000000000000000 recurse valid
211 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
213 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
216 test_cmp ../expect ../actual
219 test_expect_success 'new info/exclude invalidates everything' '
221 echo three >>.git/info/exclude &&
223 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
224 git status --porcelain >../actual &&
225 cat >../status.expect <<EOF &&
232 test_cmp ../status.expect ../actual &&
233 cat >../trace.expect <<EOF &&
235 gitignore invalidation: 1
236 directory invalidation: 0
239 test_cmp ../trace.expect ../trace
242 test_expect_success 'verify untracked cache dump' '
243 test-dump-untracked-cache >../actual &&
244 cat >../expect <<EOF &&
245 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
246 core.excludesfile 0000000000000000000000000000000000000000
247 exclude_per_dir .gitignore
249 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
252 /done/ 0000000000000000000000000000000000000000 recurse valid
253 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
254 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
257 test_cmp ../expect ../actual
260 test_expect_success 'move two from tracked to untracked' '
261 git rm --cached two &&
262 test-dump-untracked-cache >../actual &&
263 cat >../expect <<EOF &&
264 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
265 core.excludesfile 0000000000000000000000000000000000000000
266 exclude_per_dir .gitignore
268 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
269 /done/ 0000000000000000000000000000000000000000 recurse valid
270 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
271 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
274 test_cmp ../expect ../actual
277 test_expect_success 'status after the move' '
279 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
280 git status --porcelain >../actual &&
281 cat >../status.expect <<EOF &&
288 test_cmp ../status.expect ../actual &&
289 cat >../trace.expect <<EOF &&
291 gitignore invalidation: 0
292 directory invalidation: 0
295 test_cmp ../trace.expect ../trace
298 test_expect_success 'verify untracked cache dump' '
299 test-dump-untracked-cache >../actual &&
300 cat >../expect <<EOF &&
301 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
302 core.excludesfile 0000000000000000000000000000000000000000
303 exclude_per_dir .gitignore
305 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
309 /done/ 0000000000000000000000000000000000000000 recurse valid
310 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
311 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
314 test_cmp ../expect ../actual
317 test_expect_success 'move two from untracked to tracked' '
319 test-dump-untracked-cache >../actual &&
320 cat >../expect <<EOF &&
321 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
322 core.excludesfile 0000000000000000000000000000000000000000
323 exclude_per_dir .gitignore
325 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
326 /done/ 0000000000000000000000000000000000000000 recurse valid
327 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
328 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
331 test_cmp ../expect ../actual
334 test_expect_success 'status after the move' '
336 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
337 git status --porcelain >../actual &&
338 cat >../status.expect <<EOF &&
345 test_cmp ../status.expect ../actual &&
346 cat >../trace.expect <<EOF &&
348 gitignore invalidation: 0
349 directory invalidation: 0
352 test_cmp ../trace.expect ../trace
355 test_expect_success 'verify untracked cache dump' '
356 test-dump-untracked-cache >../actual &&
357 cat >../expect <<EOF &&
358 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
359 core.excludesfile 0000000000000000000000000000000000000000
360 exclude_per_dir .gitignore
362 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
365 /done/ 0000000000000000000000000000000000000000 recurse valid
366 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
367 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
370 test_cmp ../expect ../actual
373 test_expect_success 'set up for sparse checkout testing' '
374 echo two >done/.gitignore &&
375 echo three >>done/.gitignore &&
376 echo two >done/two &&
377 git add -f done/two done/.gitignore &&
378 git commit -m "first commit"
381 test_expect_success 'status after commit' '
383 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
384 git status --porcelain >../actual &&
385 cat >../status.expect <<EOF &&
389 test_cmp ../status.expect ../actual &&
390 cat >../trace.expect <<EOF &&
392 gitignore invalidation: 0
393 directory invalidation: 0
396 test_cmp ../trace.expect ../trace
399 test_expect_success 'untracked cache correct after commit' '
400 test-dump-untracked-cache >../actual &&
401 cat >../expect <<EOF &&
402 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
403 core.excludesfile 0000000000000000000000000000000000000000
404 exclude_per_dir .gitignore
406 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
409 /done/ 0000000000000000000000000000000000000000 recurse valid
410 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
411 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
414 test_cmp ../expect ../actual
417 test_expect_success 'set up sparse checkout' '
418 echo "done/[a-z]*" >.git/info/sparse-checkout &&
419 test_config core.sparsecheckout true &&
420 git checkout master &&
421 git update-index --force-untracked-cache &&
422 git status --porcelain >/dev/null && # prime the cache
423 test_path_is_missing done/.gitignore &&
424 test_path_is_file done/one
427 test_expect_success 'create/modify files, some of which are gitignored' '
428 echo two bis >done/two &&
429 echo three >done/three && # three is gitignored
430 echo four >done/four && # four is gitignored at a higher level
431 echo five >done/five && # five is not gitignored
432 echo test >base && #we need to ensure that the root dir is touched
437 test_expect_success 'test sparse status with untracked cache' '
440 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
441 git status --porcelain >../status.actual &&
442 cat >../status.expect <<EOF &&
448 test_cmp ../status.expect ../status.actual &&
449 cat >../trace.expect <<EOF &&
451 gitignore invalidation: 1
452 directory invalidation: 2
455 test_cmp ../trace.expect ../trace
458 test_expect_success 'untracked cache correct after status' '
459 test-dump-untracked-cache >../actual &&
460 cat >../expect <<EOF &&
461 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
462 core.excludesfile 0000000000000000000000000000000000000000
463 exclude_per_dir .gitignore
465 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
468 /done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
470 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
471 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
474 test_cmp ../expect ../actual
477 test_expect_success 'test sparse status again with untracked cache' '
480 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
481 git status --porcelain >../status.actual &&
482 cat >../status.expect <<EOF &&
488 test_cmp ../status.expect ../status.actual &&
489 cat >../trace.expect <<EOF &&
491 gitignore invalidation: 0
492 directory invalidation: 0
495 test_cmp ../trace.expect ../trace
498 test_expect_success 'set up for test of subdir and sparse checkouts' '
500 mkdir done/sub/sub &&
501 echo "sub" > done/sub/sub/file
504 test_expect_success 'test sparse status with untracked cache and subdir' '
507 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
508 git status --porcelain >../status.actual &&
509 cat >../status.expect <<EOF &&
516 test_cmp ../status.expect ../status.actual &&
517 cat >../trace.expect <<EOF &&
519 gitignore invalidation: 0
520 directory invalidation: 1
523 test_cmp ../trace.expect ../trace
526 test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
527 test-dump-untracked-cache >../actual &&
528 cat >../expect-from-test-dump <<EOF &&
529 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
530 core.excludesfile 0000000000000000000000000000000000000000
531 exclude_per_dir .gitignore
533 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
536 /done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
539 /done/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
541 /done/sub/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
543 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
544 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
547 test_cmp ../expect-from-test-dump ../actual
550 test_expect_success 'test sparse status again with untracked cache and subdir' '
553 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
554 git status --porcelain >../status.actual &&
555 test_cmp ../status.expect ../status.actual &&
556 cat >../trace.expect <<EOF &&
558 gitignore invalidation: 0
559 directory invalidation: 0
562 test_cmp ../trace.expect ../trace
565 test_expect_success 'move entry in subdir from untracked to cached' '
567 git status --porcelain >../status.actual &&
568 cat >../status.expect <<EOF &&
575 test_cmp ../status.expect ../status.actual
578 test_expect_success 'move entry in subdir from cached to untracked' '
579 git rm --cached dtwo/two &&
580 git status --porcelain >../status.actual &&
581 cat >../status.expect <<EOF &&
588 test_cmp ../status.expect ../status.actual
591 test_expect_success '--no-untracked-cache removes the cache' '
592 git update-index --no-untracked-cache &&
593 test-dump-untracked-cache >../actual &&
594 echo "no untracked cache" >../expect-no-uc &&
595 test_cmp ../expect-no-uc ../actual
598 test_expect_success 'git status does not change anything' '
600 test-dump-untracked-cache >../actual &&
601 test_cmp ../expect-no-uc ../actual
604 test_expect_success 'setting core.untrackedCache to true and using git status creates the cache' '
605 git config core.untrackedCache true &&
606 test-dump-untracked-cache >../actual &&
607 test_cmp ../expect-no-uc ../actual &&
609 test-dump-untracked-cache >../actual &&
610 test_cmp ../expect-from-test-dump ../actual
613 test_expect_success 'using --no-untracked-cache does not fail when core.untrackedCache is true' '
614 git update-index --no-untracked-cache &&
615 test-dump-untracked-cache >../actual &&
616 test_cmp ../expect-no-uc ../actual &&
617 git update-index --untracked-cache &&
618 test-dump-untracked-cache >../actual &&
619 test_cmp ../expect-empty ../actual
622 test_expect_success 'setting core.untrackedCache to false and using git status removes the cache' '
623 git config core.untrackedCache false &&
624 test-dump-untracked-cache >../actual &&
625 test_cmp ../expect-empty ../actual &&
627 test-dump-untracked-cache >../actual &&
628 test_cmp ../expect-no-uc ../actual
631 test_expect_success 'using --untracked-cache does not fail when core.untrackedCache is false' '
632 git update-index --untracked-cache &&
633 test-dump-untracked-cache >../actual &&
634 test_cmp ../expect-empty ../actual
637 test_expect_success 'setting core.untrackedCache to keep' '
638 git config core.untrackedCache keep &&
639 git update-index --untracked-cache &&
640 test-dump-untracked-cache >../actual &&
641 test_cmp ../expect-empty ../actual &&
643 test-dump-untracked-cache >../actual &&
644 test_cmp ../expect-from-test-dump ../actual &&
645 git update-index --no-untracked-cache &&
646 test-dump-untracked-cache >../actual &&
647 test_cmp ../expect-no-uc ../actual &&
648 git update-index --force-untracked-cache &&
649 test-dump-untracked-cache >../actual &&
650 test_cmp ../expect-empty ../actual &&
652 test-dump-untracked-cache >../actual &&
653 test_cmp ../expect-from-test-dump ../actual
656 test_expect_success 'test ident field is working' '
657 mkdir ../other_worktree &&
658 cp -R done dthree dtwo four three ../other_worktree &&
659 GIT_WORK_TREE=../other_worktree git status 2>../err &&
660 echo "warning: Untracked cache is disabled on this system or location." >../expect &&
661 test_i18ncmp ../expect ../err
664 test_expect_success 'untracked cache survives a checkout' '
665 git commit --allow-empty -m empty &&
666 test-dump-untracked-cache >../before &&
667 test_when_finished "git checkout master" &&
668 git checkout -b other_branch &&
669 test-dump-untracked-cache >../after &&
670 test_cmp ../before ../after &&
672 test-dump-untracked-cache >../before &&
673 git checkout master &&
674 test-dump-untracked-cache >../after &&
675 test_cmp ../before ../after
678 test_expect_success 'untracked cache survives a commit' '
679 test-dump-untracked-cache >../before &&
681 git commit -m commit &&
682 test-dump-untracked-cache >../after &&
683 test_cmp ../before ../after