3 test_description
='built-in file system watcher'
7 if ! test_have_prereq FSMONITOR_DAEMON
9 skip_all
="fsmonitor--daemon is not supported on this platform"
13 stop_daemon_delete_repo
() {
15 test_might_fail git
-C $r fsmonitor--daemon stop
&&
42 BUG
"error: unknown option: '$1'"
45 BUG
"error: unbound argument: '$1'"
54 GIT_TRACE_FSMONITOR
="$tf"
55 export GIT_TRACE_FSMONITOR
61 export GIT_TRACE2_PERF
66 GIT_TEST_FSMONITOR_TOKEN
="$tk"
67 export GIT_TEST_FSMONITOR_TOKEN
70 git
$r fsmonitor--daemon start
&&
71 git
$r fsmonitor--daemon status
75 # Is a Trace2 data event present with the given catetory and key?
76 # We do not care what the value is.
78 have_t2_data_event
() {
82 grep -e '"event":"data".*"category":"'"$c"'".*"key":"'"$k"'"'
85 test_expect_success
'explicit daemon start and stop' '
86 test_when_finished "stop_daemon_delete_repo test_explicit" &&
88 git init test_explicit &&
89 start_daemon -C test_explicit &&
91 git -C test_explicit fsmonitor--daemon stop &&
92 test_must_fail git -C test_explicit fsmonitor--daemon status
95 test_expect_success
'implicit daemon start' '
96 test_when_finished "stop_daemon_delete_repo test_implicit" &&
98 git init test_implicit &&
99 test_must_fail git -C test_implicit fsmonitor--daemon status &&
101 # query will implicitly start the daemon.
103 # for test-script simplicity, we send a V1 timestamp rather than
104 # a V2 token. either way, the daemon response to any query contains
105 # a new V2 token. (the daemon may complain that we sent a V1 request,
106 # but this test case is only concerned with whether the daemon was
107 # implicitly started.)
109 GIT_TRACE2_EVENT="$PWD/.git/trace" \
110 test-tool -C test_implicit fsmonitor-client query --token 0 >actual &&
111 nul_to_q <actual >actual.filtered &&
112 grep "builtin:" actual.filtered &&
114 # confirm that a daemon was started in the background.
116 # since the mechanism for starting the background daemon is platform
117 # dependent, just confirm that the foreground command received a
118 # response from the daemon.
120 have_t2_data_event fsm_client query/response-length <.git/trace &&
122 git -C test_implicit fsmonitor--daemon status &&
123 git -C test_implicit fsmonitor--daemon stop &&
124 test_must_fail git -C test_implicit fsmonitor--daemon status
127 # Verify that the daemon has shutdown. Spin a few seconds to
128 # make the test a little more robust during CI testing.
130 # We're looking for an implicit shutdown, such as when we delete or
131 # rename the ".git" directory. Our delete/rename will cause a file
132 # system event that the daemon will see and the daemon will
133 # auto-shutdown as soon as it sees it. But this is racy with our `git
134 # fsmonitor--daemon status` commands (and we cannot use a cookie file
135 # here to help us). So spin a little and give the daemon a chance to
136 # see the event. (This is primarily for underpowered CI build/test
137 # machines (where it might take a moment to wake and reschedule the
138 # daemon process) to avoid false alarms during test runs.)
142 verify_implicit_shutdown
() {
146 while test "$k" -lt $IMPLICIT_TIMEOUT
148 git
-C $r fsmonitor--daemon status ||
return 0
157 test_expect_success
'implicit daemon stop (delete .git)' '
158 test_when_finished "stop_daemon_delete_repo test_implicit_1" &&
160 git init test_implicit_1 &&
162 start_daemon -C test_implicit_1 &&
164 # deleting the .git directory will implicitly stop the daemon.
165 rm -rf test_implicit_1/.git &&
167 # [1] Create an empty .git directory so that the following Git
168 # command will stay relative to the `-C` directory.
170 # Without this, the Git command will override the requested
171 # -C argument and crawl out to the containing Git source tree.
172 # This would make the test result dependent upon whether we
173 # were using fsmonitor on our development worktree.
175 mkdir test_implicit_1/.git &&
177 verify_implicit_shutdown test_implicit_1
180 test_expect_success
'implicit daemon stop (rename .git)' '
181 test_when_finished "stop_daemon_delete_repo test_implicit_2" &&
183 git init test_implicit_2 &&
185 start_daemon -C test_implicit_2 &&
187 # renaming the .git directory will implicitly stop the daemon.
188 mv test_implicit_2/.git test_implicit_2/.xxx &&
192 mkdir test_implicit_2/.git &&
194 verify_implicit_shutdown test_implicit_2
197 # File systems on Windows may or may not have shortnames.
198 # This is a volume-specific setting on modern systems.
199 # "C:/" drives are required to have them enabled. Other
200 # hard drives default to disabled.
202 # This is a crude test to see if shortnames are enabled
203 # on the volume containing the test directory. It is
204 # crude, but it does not require elevation like `fsutil`.
206 test_lazy_prereq SHORTNAMES
'
211 # Here we assume that the shortname of ".git" is "GIT~1".
212 test_expect_success MINGW
,SHORTNAMES
'implicit daemon stop (rename GIT~1)' '
213 test_when_finished "stop_daemon_delete_repo test_implicit_1s" &&
215 git init test_implicit_1s &&
217 start_daemon -C test_implicit_1s &&
219 # renaming the .git directory will implicitly stop the daemon.
220 # this moves {.git, GIT~1} to {.gitxyz, GITXYZ~1}.
221 # the rename-from FS Event will contain the shortname.
223 mv test_implicit_1s/GIT~1 test_implicit_1s/.gitxyz &&
226 # this moves {.gitxyz, GITXYZ~1} to {.git, GIT~1}.
227 mv test_implicit_1s/.gitxyz test_implicit_1s/.git &&
229 verify_implicit_shutdown test_implicit_1s
232 # Here we first create a file with LONGNAME of "GIT~1" before
233 # we create the repo. This will cause the shortname of ".git"
235 test_expect_success MINGW
,SHORTNAMES
'implicit daemon stop (rename GIT~2)' '
236 test_when_finished "stop_daemon_delete_repo test_implicit_1s2" &&
238 mkdir test_implicit_1s2 &&
239 echo HELLO >test_implicit_1s2/GIT~1 &&
240 git init test_implicit_1s2 &&
242 test_path_is_file test_implicit_1s2/GIT~1 &&
243 test_path_is_dir test_implicit_1s2/GIT~2 &&
245 start_daemon -C test_implicit_1s2 &&
247 # renaming the .git directory will implicitly stop the daemon.
248 # the rename-from FS Event will contain the shortname.
250 mv test_implicit_1s2/GIT~2 test_implicit_1s2/.gitxyz &&
253 mv test_implicit_1s2/.gitxyz test_implicit_1s2/.git &&
255 verify_implicit_shutdown test_implicit_1s2
258 test_expect_success
'cannot start multiple daemons' '
259 test_when_finished "stop_daemon_delete_repo test_multiple" &&
261 git init test_multiple &&
263 start_daemon -C test_multiple &&
265 test_must_fail git -C test_multiple fsmonitor--daemon start 2>actual &&
266 grep "fsmonitor--daemon is already running" actual &&
268 git -C test_multiple fsmonitor--daemon stop &&
269 test_must_fail git -C test_multiple fsmonitor--daemon status
272 # These tests use the main repo in the trash directory
274 test_expect_success
'setup' '
293 cat >.gitignore <<-\EOF &&
301 mkdir -p T1/T2/T3/T4 &&
304 echo 1 >T1/T2/T3/F1 &&
305 echo 1 >T1/T2/T3/T4/F1 &&
308 echo 2 >T1/T2/T3/F2 &&
309 echo 2 >T1/T2/T3/T4/F2 &&
311 git -c core.fsmonitor=false add . &&
313 git -c core.fsmonitor=false commit -m initial &&
315 git config core.fsmonitor true
318 # The test already explicitly stopped (or tried to stop) the daemon.
319 # This is here in case something else fails first.
321 redundant_stop_daemon
() {
322 test_might_fail git fsmonitor--daemon stop
325 test_expect_success
'update-index implicitly starts daemon' '
326 test_when_finished redundant_stop_daemon &&
328 test_must_fail git fsmonitor--daemon status &&
330 GIT_TRACE2_EVENT="$PWD/.git/trace_implicit_1" \
331 git update-index --fsmonitor &&
333 git fsmonitor--daemon status &&
334 test_might_fail git fsmonitor--daemon stop &&
336 # Confirm that the trace2 log contains a record of the
338 test_subcommand git fsmonitor--daemon start <.git/trace_implicit_1
341 test_expect_success
'status implicitly starts daemon' '
342 test_when_finished redundant_stop_daemon &&
344 test_must_fail git fsmonitor--daemon status &&
346 GIT_TRACE2_EVENT="$PWD/.git/trace_implicit_2" \
347 git status >actual &&
349 git fsmonitor--daemon status &&
350 test_might_fail git fsmonitor--daemon stop &&
352 # Confirm that the trace2 log contains a record of the
354 test_subcommand git fsmonitor--daemon start <.git/trace_implicit_2
359 echo 2 >dir
1/modified
&&
360 echo 3 >dir
2/modified
&&
378 mv dir
1/rename dir
1/renamed
&&
379 mv dir
2/rename dir
2/renamed
382 file_to_directory
() {
388 directory_to_file
() {
393 move_directory_contents_deeper
() {
395 mv T
1/[A-Z
]* T
1/_new_
398 move_directory_up
() {
403 mv T
1/T
2/T3 T
1/T
2/NewT3
406 # The next few test cases confirm that our fsmonitor daemon sees each type
407 # of OS filesystem notification that we care about. At this layer we just
408 # ensure we are getting the OS notifications and do not try to confirm what
409 # is reported by `git status`.
411 # We run a simple query after modifying the filesystem just to introduce
412 # a bit of a delay so that the trace logging from the daemon has time to
413 # get flushed to disk.
415 # We `reset` and `clean` at the bottom of each test (and before stopping the
416 # daemon) because these commands might implicitly restart the daemon.
418 clean_up_repo_and_stop_daemon
() {
419 git
reset --hard HEAD
&&
421 test_might_fail git fsmonitor--daemon stop
&&
425 test_expect_success
'edit some files' '
426 test_when_finished clean_up_repo_and_stop_daemon &&
428 start_daemon --tf "$PWD/.git/trace" &&
432 test-tool fsmonitor-client query --token 0 &&
434 grep "^event: dir1/modified$" .git/trace &&
435 grep "^event: dir2/modified$" .git/trace &&
436 grep "^event: modified$" .git/trace &&
437 grep "^event: dir1/untracked$" .git/trace
440 test_expect_success
'create some files' '
441 test_when_finished clean_up_repo_and_stop_daemon &&
443 start_daemon --tf "$PWD/.git/trace" &&
447 test-tool fsmonitor-client query --token 0 &&
449 grep "^event: dir1/new$" .git/trace &&
450 grep "^event: dir2/new$" .git/trace &&
451 grep "^event: new$" .git/trace
454 test_expect_success
'delete some files' '
455 test_when_finished clean_up_repo_and_stop_daemon &&
457 start_daemon --tf "$PWD/.git/trace" &&
461 test-tool fsmonitor-client query --token 0 &&
463 grep "^event: dir1/delete$" .git/trace &&
464 grep "^event: dir2/delete$" .git/trace &&
465 grep "^event: delete$" .git/trace
468 test_expect_success
'rename some files' '
469 test_when_finished clean_up_repo_and_stop_daemon &&
471 start_daemon --tf "$PWD/.git/trace" &&
475 test-tool fsmonitor-client query --token 0 &&
477 grep "^event: dir1/rename$" .git/trace &&
478 grep "^event: dir2/rename$" .git/trace &&
479 grep "^event: rename$" .git/trace &&
480 grep "^event: dir1/renamed$" .git/trace &&
481 grep "^event: dir2/renamed$" .git/trace &&
482 grep "^event: renamed$" .git/trace
485 test_expect_success
'rename directory' '
486 test_when_finished clean_up_repo_and_stop_daemon &&
488 start_daemon --tf "$PWD/.git/trace" &&
490 mv dirtorename dirrenamed &&
492 test-tool fsmonitor-client query --token 0 &&
494 grep "^event: dirtorename/*$" .git/trace &&
495 grep "^event: dirrenamed/*$" .git/trace
498 test_expect_success
'file changes to directory' '
499 test_when_finished clean_up_repo_and_stop_daemon &&
501 start_daemon --tf "$PWD/.git/trace" &&
505 test-tool fsmonitor-client query --token 0 &&
507 grep "^event: delete$" .git/trace &&
508 grep "^event: delete/new$" .git/trace
511 test_expect_success
'directory changes to a file' '
512 test_when_finished clean_up_repo_and_stop_daemon &&
514 start_daemon --tf "$PWD/.git/trace" &&
518 test-tool fsmonitor-client query --token 0 &&
520 grep "^event: dir1$" .git/trace
523 # The next few test cases exercise the token-resync code. When filesystem
524 # drops events (because of filesystem velocity or because the daemon isn't
525 # polling fast enough), we need to discard the cached data (relative to the
526 # current token) and start collecting events under a new token.
528 # the 'test-tool fsmonitor-client flush' command can be used to send a
529 # "flush" message to a running daemon and ask it to do a flush/resync.
531 test_expect_success
'flush cached data' '
532 test_when_finished "stop_daemon_delete_repo test_flush" &&
534 git init test_flush &&
536 start_daemon -C test_flush --tf "$PWD/.git/trace_daemon" --tk true &&
538 # The daemon should have an initial token with no events in _0 and
539 # then a few (probably platform-specific number of) events in _1.
540 # These should both have the same <token_id>.
542 test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000001:0" >actual_0 &&
543 nul_to_q <actual_0 >actual_q0 &&
545 >test_flush/file_1 &&
546 >test_flush/file_2 &&
548 test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000001:0" >actual_1 &&
549 nul_to_q <actual_1 >actual_q1 &&
551 grep "file_1" actual_q1 &&
553 # Force a flush. This will change the <token_id>, reset the <seq_nr>, and
554 # flush the file data. Then create some events and ensure that the file
555 # again appears in the cache. It should have the new <token_id>.
557 test-tool -C test_flush fsmonitor-client flush >flush_0 &&
558 nul_to_q <flush_0 >flush_q0 &&
559 grep "^builtin:test_00000002:0Q/Q$" flush_q0 &&
561 test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000002:0" >actual_2 &&
562 nul_to_q <actual_2 >actual_q2 &&
564 grep "^builtin:test_00000002:0Q$" actual_q2 &&
566 >test_flush/file_3 &&
568 test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000002:0" >actual_3 &&
569 nul_to_q <actual_3 >actual_q3 &&
571 grep "file_3" actual_q3
574 # The next few test cases create repos where the .git directory is NOT
575 # inside the one of the working directory. That is, where .git is a file
576 # that points to a directory elsewhere. This happens for submodules and
577 # non-primary worktrees.
579 test_expect_success
'setup worktree base' '
581 echo 1 >wt-base/file1 &&
582 git -C wt-base add file1 &&
583 git -C wt-base commit -m "c1"
586 test_expect_success
'worktree with .git file' '
587 git -C wt-base worktree add ../wt-secondary &&
589 start_daemon -C wt-secondary \
590 --tf "$PWD/trace_wt_secondary" \
591 --t2 "$PWD/trace2_wt_secondary" &&
593 git -C wt-secondary fsmonitor--daemon stop &&
594 test_must_fail git -C wt-secondary fsmonitor--daemon status
597 # NEEDSWORK: Repeat one of the "edit" tests on wt-secondary and
598 # confirm that we get the same events and behavior -- that is, that
599 # fsmonitor--daemon correctly watches BOTH the working directory and
600 # the external GITDIR directory and behaves the same as when ".git"
601 # is a directory inside the working directory.
603 test_expect_success
'cleanup worktrees' '
604 stop_daemon_delete_repo wt-secondary &&
605 stop_daemon_delete_repo wt-base
608 # The next few tests perform arbitrary/contrived file operations and
609 # confirm that status is correct. That is, that the data (or lack of
610 # data) from fsmonitor doesn't cause incorrect results. And doesn't
611 # cause incorrect results when the untracked-cache is enabled.
613 test_lazy_prereq UNTRACKED_CACHE
'
614 git update-index --test-untracked-cache
617 test_expect_success
'Matrix: setup for untracked-cache,fsmonitor matrix' '
618 test_unconfig core.fsmonitor &&
619 git update-index --no-fsmonitor &&
620 test_might_fail git fsmonitor--daemon stop
623 matrix_clean_up_repo
() {
624 git
reset --hard HEAD
&&
633 if test $uc = true
&& test $fsm = false
635 # The untracked-cache is buggy when FSMonitor is
636 # DISABLED, so skip the tests for this matrix
639 # We've observed random, occasional test failures on
640 # Windows and MacOS when the UC is turned on and FSM
641 # is turned off. These are rare, but they do happen
642 # indicating that it is probably a race condition within
643 # the untracked cache itself.
645 # It usually happens when a test does F/D trickery and
646 # then the NEXT test fails because of extra status
647 # output from stale UC data from the previous test.
649 # Since FSMonitor is not involved in the error, skip
650 # the tests for this matrix combination.
655 test_expect_success
"Matrix[uc:$uc][fsm:$fsm] $fn" '
656 matrix_clean_up_repo &&
658 if test $uc = false && test $fsm = false
660 git status --porcelain=v1 >.git/expect.$fn
662 git status --porcelain=v1 >.git/actual.$fn &&
663 test_cmp .git/expect.$fn .git/actual.$fn
669 test_have_prereq UNTRACKED_CACHE
&& uc_values
="false true"
670 for uc_val
in $uc_values
672 if test $uc_val = false
674 test_expect_success
"Matrix[uc:$uc_val] disable untracked cache" '
675 git config core.untrackedcache false &&
676 git update-index --no-untracked-cache
679 test_expect_success
"Matrix[uc:$uc_val] enable untracked cache" '
680 git config core.untrackedcache true &&
681 git update-index --untracked-cache
685 fsm_values
="false true"
686 for fsm_val
in $fsm_values
688 if test $fsm_val = false
690 test_expect_success
"Matrix[uc:$uc_val][fsm:$fsm_val] disable fsmonitor" '
691 test_unconfig core.fsmonitor &&
692 git update-index --no-fsmonitor &&
693 test_might_fail git fsmonitor--daemon stop
696 test_expect_success
"Matrix[uc:$uc_val][fsm:$fsm_val] enable fsmonitor" '
697 git config core.fsmonitor true &&
698 git fsmonitor--daemon start &&
699 git update-index --fsmonitor
703 matrix_try
$uc_val $fsm_val edit_files
704 matrix_try
$uc_val $fsm_val delete_files
705 matrix_try
$uc_val $fsm_val create_files
706 matrix_try
$uc_val $fsm_val rename_files
707 matrix_try
$uc_val $fsm_val file_to_directory
708 matrix_try
$uc_val $fsm_val directory_to_file
710 matrix_try
$uc_val $fsm_val move_directory_contents_deeper
711 matrix_try
$uc_val $fsm_val move_directory_up
712 matrix_try
$uc_val $fsm_val move_directory
714 if test $fsm_val = true
716 test_expect_success
"Matrix[uc:$uc_val][fsm:$fsm_val] disable fsmonitor at end" '
717 test_unconfig core.fsmonitor &&
718 git update-index --no-fsmonitor &&
719 test_might_fail git fsmonitor--daemon stop
725 # Test Unicode UTF-8 characters in the pathname of the working
726 # directory root. Use of "*A()" routines rather than "*W()" routines
727 # on Windows can sometimes lead to odd failures.
729 u1
=$
(printf "u_c3_a6__\xC3\xA6")
730 u2
=$
(printf "u_e2_99_ab__\xE2\x99\xAB")
734 test_expect_success
"unicode in repo root path: $u" '
735 test_when_finished "stop_daemon_delete_repo $u" &&
738 echo 1 >"$u"/file1 &&
739 git -C "$u" add file1 &&
740 git -C "$u" config core.fsmonitor true &&
742 start_daemon -C "$u" &&
743 git -C "$u" status >actual &&
744 grep "new file: file1" actual
748 # Test fsmonitor interaction with submodules.
750 # If we start the daemon in the super, it will see FS events for
751 # everything in the working directory cone and this includes any
752 # files/directories contained *within* the submodules.
754 # A `git status` at top level will get events for items within the
755 # submodule and ignore them, since they aren't named in the index
756 # of the super repo. This makes the fsmonitor response a little
757 # noisy, but it doesn't alter the correctness of the state of the
760 # When we have submodules, `git status` normally does a recursive
761 # status on each of the submodules and adds a summary row for any
762 # dirty submodules. (See the "S..." bits in porcelain V2 output.)
764 # It is therefore important that the top level status not be tricked
765 # by the FSMonitor response to skip those recursive calls. That is,
766 # even if FSMonitor says that the mtime of the submodule directory
767 # hasn't changed and it could be implicitly marked valid, we must
768 # not take that shortcut. We need to force the recusion into the
769 # submodule so that we get a summary of the status *within* the
776 echo x
>"$super/file_1" &&
777 echo y
>"$super/file_2" &&
778 echo z
>"$super/file_3" &&
779 mkdir
"$super/dir_1" &&
780 echo a
>"$super/dir_1/file_11" &&
781 echo b
>"$super/dir_1/file_12" &&
782 mkdir
"$super/dir_1/dir_2" &&
783 echo a
>"$super/dir_1/dir_2/file_21" &&
784 echo b
>"$super/dir_1/dir_2/file_22" &&
785 git
-C "$super" add .
&&
786 git
-C "$super" commit
-m "initial $super commit"
793 echo x
>"$sub/file_x" &&
794 echo y
>"$sub/file_y" &&
795 echo z
>"$sub/file_z" &&
796 mkdir
"$sub/dir_x" &&
797 echo a
>"$sub/dir_x/file_a" &&
798 echo b
>"$sub/dir_x/file_b" &&
799 mkdir
"$sub/dir_x/dir_y" &&
800 echo a
>"$sub/dir_x/dir_y/file_a" &&
801 echo b
>"$sub/dir_x/dir_y/file_b" &&
802 git
-C "$sub" add .
&&
803 git
-C "$sub" commit
-m "initial $sub commit"
806 my_match_and_clean
() {
807 git
-C super
--no-optional-locks status
--porcelain=v2
>actual.with
&&
808 git
-C super
--no-optional-locks -c core.fsmonitor
=false \
809 status
--porcelain=v2
>actual.without
&&
810 test_cmp actual.with actual.without
&&
812 git
-C super
/dir_
1/dir_
2/sub
reset --hard &&
813 git
-C super
/dir_
1/dir_
2/sub clean
-d -f
816 test_expect_success
'submodule setup' '
817 git config --global protocol.file.allow always
820 test_expect_success
'submodule always visited' '
821 test_when_finished "git -C super fsmonitor--daemon stop; \
825 create_super super &&
828 git -C super submodule add ../sub ./dir_1/dir_2/sub &&
829 git -C super commit -m "add sub" &&
831 start_daemon -C super &&
832 git -C super config core.fsmonitor true &&
833 git -C super update-index --fsmonitor &&
834 git -C super status &&
836 # Now run pairs of commands w/ and w/o FSMonitor while we make
837 # some dirt in the submodule and confirm matching output.
839 # Completely clean status.
840 my_match_and_clean &&
843 echo z >super/dir_1/dir_2/sub/dir_x/dir_y/foobar_u &&
844 my_match_and_clean &&
847 echo z >super/dir_1/dir_2/sub/dir_x/dir_y/foobar_m &&
848 git -C super/dir_1/dir_2/sub add . &&
849 my_match_and_clean &&
852 echo z >>super/dir_1/dir_2/sub/dir_x/dir_y/file_a &&
853 git -C super/dir_1/dir_2/sub add . &&
854 my_match_and_clean &&
857 echo z >>super/dir_1/dir_2/sub/dir_x/dir_y/file_a &&
858 git -C super/dir_1/dir_2/sub add . &&
859 git -C super/dir_1/dir_2/sub commit -m "SC.." &&
863 # If a submodule has a `sub/.git/` directory (rather than a file
864 # pointing to the super's `.git/modules/sub`) and `core.fsmonitor`
865 # turned on in the submodule and the daemon is not yet started in
866 # the submodule, and someone does a `git submodule absorbgitdirs`
867 # in the super, Git will recursively invoke `git submodule--helper`
868 # to do the work and this may try to read the index. This will
869 # try to start the daemon in the submodule.
871 test_expect_success
"submodule absorbgitdirs implicitly starts daemon" '
872 test_when_finished "rm -rf super; \
874 rm super-sub.trace" &&
876 create_super super &&
879 # Copy rather than submodule add so that we get a .git dir.
880 cp -R ./sub ./super/dir_1/dir_2/sub &&
882 git -C super/dir_1/dir_2/sub config core.fsmonitor true &&
884 git -C super submodule add ../sub ./dir_1/dir_2/sub &&
885 git -C super commit -m "add sub" &&
887 test_path_is_dir super/dir_1/dir_2/sub/.git &&
889 cwd="$(cd super && pwd)" &&
890 cat >expect <<-EOF &&
891 Migrating git directory of '\''dir_1/dir_2/sub'\'' from
892 '\''$cwd/dir_1/dir_2/sub/.git'\'' to
893 '\''$cwd/.git/modules/dir_1/dir_2/sub'\''
895 GIT_TRACE2_EVENT="$PWD/super-sub.trace" \
896 git -C super submodule absorbgitdirs >out 2>actual &&
897 test_cmp expect actual &&
898 test_must_be_empty out &&
900 # Confirm that the trace2 log contains a record of the
902 test_subcommand git fsmonitor--daemon start <super-sub.trace
905 # On a case-insensitive file system, confirm that the daemon
906 # notices when the .git directory is moved/renamed/deleted
907 # regardless of how it is spelled in the FS event.
908 # That is, does the FS event receive the spelling of the
909 # operation or does it receive the spelling preserved with
910 # the file/directory.
912 test_expect_success CASE_INSENSITIVE_FS
'case insensitive+preserving' '
913 test_when_finished "stop_daemon_delete_repo test_insensitive" &&
915 git init test_insensitive &&
917 start_daemon -C test_insensitive --tf "$PWD/insensitive.trace" &&
919 mkdir -p test_insensitive/abc/def &&
920 echo xyz >test_insensitive/ABC/DEF/xyz &&
922 test_path_is_dir test_insensitive/.git &&
923 test_path_is_dir test_insensitive/.GIT &&
925 # Rename .git using an alternate spelling to verify that
926 # the daemon detects it and automatically shuts down.
927 mv test_insensitive/.GIT test_insensitive/.FOO &&
930 mv test_insensitive/.FOO test_insensitive/.git &&
932 verify_implicit_shutdown test_insensitive &&
934 # Verify that events were reported using on-disk spellings of the
935 # directories and files that we touched. We may or may not get a
936 # trailing slash on modified directories.
938 grep -E "^event: abc/?$" ./insensitive.trace &&
939 grep -E "^event: abc/def/?$" ./insensitive.trace &&
940 grep -E "^event: abc/def/xyz$" ./insensitive.trace
943 # The variable "unicode_debug" is defined in the following library
944 # script to dump information about how the (OS, FS) handles Unicode
945 # composition. Uncomment the following line if you want to enable it.
949 .
"$TEST_DIRECTORY/lib-unicode-nfc-nfd.sh"
951 # See if the OS or filesystem does NFC/NFD aliasing/munging.
953 # The daemon should err on the side of caution and send BOTH the
954 # NFC and NFD forms. It does not know the original spelling of
955 # the pathname (how the user thinks it should be spelled), so
956 # emit both and let the client decide (when necessary). This is
957 # similar to "core.precomposeUnicode".
959 test_expect_success
!UNICODE_COMPOSITION_SENSITIVE
'Unicode nfc/nfd' '
960 test_when_finished "stop_daemon_delete_repo test_unicode" &&
962 git init test_unicode &&
964 start_daemon -C test_unicode --tf "$PWD/unicode.trace" &&
966 # Create a directory using an NFC spelling.
968 mkdir test_unicode/nfc &&
969 mkdir test_unicode/nfc/c_${utf8_nfc} &&
971 # Create a directory using an NFD spelling.
973 mkdir test_unicode/nfd &&
974 mkdir test_unicode/nfd/d_${utf8_nfd} &&
976 git -C test_unicode fsmonitor--daemon stop &&
978 if test_have_prereq UNICODE_NFC_PRESERVED
980 # We should have seen NFC event from OS.
981 # We should not have synthesized an NFD event.
982 grep -E "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace &&
983 grep -E -v "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace
985 # We should have seen NFD event from OS.
986 # We should have synthesized an NFC event.
987 grep -E "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace &&
988 grep -E "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace
991 # We assume UNICODE_NFD_PRESERVED.
992 # We should have seen explicit NFD from OS.
993 # We should have synthesized an NFC event.
994 grep -E "^event: nfd/d_${utf8_nfd}/?$" ./unicode.trace &&
995 grep -E "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
998 test_expect_success
'split-index and FSMonitor work well together' '
999 git init split-index &&
1000 test_when_finished "git -C \"$PWD/split-index\" \
1001 fsmonitor--daemon stop" &&
1004 git config core.splitIndex true &&
1005 # force split-index in most cases
1006 git config splitIndex.maxPercentChange 99 &&
1007 git config core.fsmonitor true &&
1009 # Create the following commit topology:
1021 test_commit initial &&
1023 test_commit three &&
1024 git reset --hard initial &&
1031 git rebase --force-rebase -r one