Merge branch 'mg/timestamp-t-fix' into maint
[git/debian.git] / t / t7063-status-untracked-cache.sh
blobe5fb892f9575fda4baf0b2a0e6b31cf13a0d6c0b
1 #!/bin/sh
3 test_description='test untracked cache'
5 . ./test-lib.sh
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
15 # more.
17 sync_mtime () {
18 find . -type d -ls >/dev/null
21 avoid_racy() {
22 sleep 1
25 test_lazy_prereq UNTRACKED_CACHE '
26 { git update-index --test-untracked-cache; ret=$?; } &&
27 test $ret -ne 1
30 if ! test_have_prereq UNTRACKED_CACHE; then
31 skip_all='This system does not support untracked cache'
32 test_done
35 test_expect_success 'core.untrackedCache is unset' '
36 test_must_fail git config --get core.untrackedCache
39 test_expect_success 'setup' '
40 git init worktree &&
41 cd worktree &&
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
55 flags 00000006
56 EOF
57 test_cmp ../expect-empty ../actual
60 cat >../status.expect <<EOF &&
61 A done/one
62 A one
63 A two
64 ?? dthree/
65 ?? dtwo/
66 ?? three
67 EOF
69 cat >../dump.expect <<EOF &&
70 info/exclude $EMPTY_BLOB
71 core.excludesfile 0000000000000000000000000000000000000000
72 exclude_per_dir .gitignore
73 flags 00000006
74 / 0000000000000000000000000000000000000000 recurse valid
75 dthree/
76 dtwo/
77 three
78 /done/ 0000000000000000000000000000000000000000 recurse valid
79 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
80 three
81 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
82 two
83 EOF
85 test_expect_success 'status first time (empty cache)' '
86 avoid_racy &&
87 : >../trace &&
88 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
89 git status --porcelain >../actual &&
90 test_cmp ../status.expect ../actual &&
91 cat >../trace.expect <<EOF &&
92 node creation: 3
93 gitignore invalidation: 1
94 directory invalidation: 0
95 opendir: 4
96 EOF
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)' '
106 avoid_racy &&
107 : >../trace &&
108 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
109 git status --porcelain >../actual &&
110 test_cmp ../status.expect ../actual &&
111 cat >../trace.expect <<EOF &&
112 node creation: 0
113 gitignore invalidation: 0
114 directory invalidation: 0
115 opendir: 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' '
126 avoid_racy &&
127 : >four &&
128 : >../trace &&
129 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
130 git status --porcelain >../actual &&
131 cat >../status.expect <<EOF &&
132 A done/one
133 A one
134 A two
135 ?? dthree/
136 ?? dtwo/
137 ?? four
138 ?? three
140 test_cmp ../status.expect ../actual &&
141 cat >../trace.expect <<EOF &&
142 node creation: 0
143 gitignore invalidation: 0
144 directory invalidation: 1
145 opendir: 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
157 flags 00000006
158 / 0000000000000000000000000000000000000000 recurse valid
159 dthree/
160 dtwo/
161 four
162 three
163 /done/ 0000000000000000000000000000000000000000 recurse valid
164 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
165 three
166 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
169 test_cmp ../expect ../actual
172 test_expect_success 'new .gitignore invalidates recursively' '
173 avoid_racy &&
174 echo four >.gitignore &&
175 : >../trace &&
176 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
177 git status --porcelain >../actual &&
178 cat >../status.expect <<EOF &&
179 A done/one
180 A one
181 A two
182 ?? .gitignore
183 ?? dthree/
184 ?? dtwo/
185 ?? three
187 test_cmp ../status.expect ../actual &&
188 cat >../trace.expect <<EOF &&
189 node creation: 0
190 gitignore invalidation: 1
191 directory invalidation: 1
192 opendir: 4
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
204 flags 00000006
205 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
206 .gitignore
207 dthree/
208 dtwo/
209 three
210 /done/ 0000000000000000000000000000000000000000 recurse valid
211 /dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
212 three
213 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
216 test_cmp ../expect ../actual
219 test_expect_success 'new info/exclude invalidates everything' '
220 avoid_racy &&
221 echo three >>.git/info/exclude &&
222 : >../trace &&
223 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
224 git status --porcelain >../actual &&
225 cat >../status.expect <<EOF &&
226 A done/one
227 A one
228 A two
229 ?? .gitignore
230 ?? dtwo/
232 test_cmp ../status.expect ../actual &&
233 cat >../trace.expect <<EOF &&
234 node creation: 0
235 gitignore invalidation: 1
236 directory invalidation: 0
237 opendir: 4
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
248 flags 00000006
249 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
250 .gitignore
251 dtwo/
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
267 flags 00000006
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' '
278 : >../trace &&
279 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
280 git status --porcelain >../actual &&
281 cat >../status.expect <<EOF &&
282 A done/one
283 A one
284 ?? .gitignore
285 ?? dtwo/
286 ?? two
288 test_cmp ../status.expect ../actual &&
289 cat >../trace.expect <<EOF &&
290 node creation: 0
291 gitignore invalidation: 0
292 directory invalidation: 0
293 opendir: 1
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
304 flags 00000006
305 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
306 .gitignore
307 dtwo/
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' '
318 git add two &&
319 test-dump-untracked-cache >../actual &&
320 cat >../expect <<EOF &&
321 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
322 core.excludesfile 0000000000000000000000000000000000000000
323 exclude_per_dir .gitignore
324 flags 00000006
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' '
335 : >../trace &&
336 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
337 git status --porcelain >../actual &&
338 cat >../status.expect <<EOF &&
339 A done/one
340 A one
341 A two
342 ?? .gitignore
343 ?? dtwo/
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
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
361 flags 00000006
362 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
363 .gitignore
364 dtwo/
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' '
382 : >../trace &&
383 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
384 git status --porcelain >../actual &&
385 cat >../status.expect <<EOF &&
386 ?? .gitignore
387 ?? dtwo/
389 test_cmp ../status.expect ../actual &&
390 cat >../trace.expect <<EOF &&
391 node creation: 0
392 gitignore invalidation: 0
393 directory invalidation: 0
394 opendir: 2
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
405 flags 00000006
406 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
407 .gitignore
408 dtwo/
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
433 rm base &&
434 sync_mtime
437 test_expect_success 'test sparse status with untracked cache' '
438 : >../trace &&
439 avoid_racy &&
440 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
441 git status --porcelain >../status.actual &&
442 cat >../status.expect <<EOF &&
443 M done/two
444 ?? .gitignore
445 ?? done/five
446 ?? dtwo/
448 test_cmp ../status.expect ../status.actual &&
449 cat >../trace.expect <<EOF &&
450 node creation: 0
451 gitignore invalidation: 1
452 directory invalidation: 2
453 opendir: 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
464 flags 00000006
465 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
466 .gitignore
467 dtwo/
468 /done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
469 five
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' '
478 avoid_racy &&
479 : >../trace &&
480 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
481 git status --porcelain >../status.actual &&
482 cat >../status.expect <<EOF &&
483 M done/two
484 ?? .gitignore
485 ?? done/five
486 ?? dtwo/
488 test_cmp ../status.expect ../status.actual &&
489 cat >../trace.expect <<EOF &&
490 node creation: 0
491 gitignore invalidation: 0
492 directory invalidation: 0
493 opendir: 0
495 test_cmp ../trace.expect ../trace
498 test_expect_success 'set up for test of subdir and sparse checkouts' '
499 mkdir done/sub &&
500 mkdir done/sub/sub &&
501 echo "sub" > done/sub/sub/file
504 test_expect_success 'test sparse status with untracked cache and subdir' '
505 avoid_racy &&
506 : >../trace &&
507 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
508 git status --porcelain >../status.actual &&
509 cat >../status.expect <<EOF &&
510 M done/two
511 ?? .gitignore
512 ?? done/five
513 ?? done/sub/
514 ?? dtwo/
516 test_cmp ../status.expect ../status.actual &&
517 cat >../trace.expect <<EOF &&
518 node creation: 2
519 gitignore invalidation: 0
520 directory invalidation: 1
521 opendir: 3
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
532 flags 00000006
533 / e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
534 .gitignore
535 dtwo/
536 /done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
537 five
538 sub/
539 /done/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
540 sub/
541 /done/sub/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
542 file
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' '
551 avoid_racy &&
552 : >../trace &&
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 &&
557 node creation: 0
558 gitignore invalidation: 0
559 directory invalidation: 0
560 opendir: 0
562 test_cmp ../trace.expect ../trace
565 test_expect_success 'move entry in subdir from untracked to cached' '
566 git add dtwo/two &&
567 git status --porcelain >../status.actual &&
568 cat >../status.expect <<EOF &&
569 M done/two
570 A dtwo/two
571 ?? .gitignore
572 ?? done/five
573 ?? done/sub/
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 &&
582 M done/two
583 ?? .gitignore
584 ?? done/five
585 ?? done/sub/
586 ?? dtwo/
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' '
599 git status &&
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 &&
608 git status &&
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 &&
626 git status &&
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 &&
642 git status &&
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 &&
651 git status &&
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 &&
671 test_commit test &&
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 &&
680 git add done/two &&
681 git commit -m commit &&
682 test-dump-untracked-cache >../after &&
683 test_cmp ../before ../after
686 test_done