summaryrefslogtreecommitdiff
path: root/t/t7527-builtin-fsmonitor.sh
diff options
context:
space:
mode:
Diffstat (limited to 't/t7527-builtin-fsmonitor.sh')
-rwxr-xr-xt/t7527-builtin-fsmonitor.sh333
1 files changed, 297 insertions, 36 deletions
diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh
index 56c0dff..730f3c7 100755
--- a/t/t7527-builtin-fsmonitor.sh
+++ b/t/t7527-builtin-fsmonitor.sh
@@ -809,10 +809,19 @@ my_match_and_clean () {
status --porcelain=v2 >actual.without &&
test_cmp actual.with actual.without &&
+ git -C super --no-optional-locks diff-index --name-status HEAD >actual.with &&
+ git -C super --no-optional-locks -c core.fsmonitor=false \
+ diff-index --name-status HEAD >actual.without &&
+ test_cmp actual.with actual.without &&
+
git -C super/dir_1/dir_2/sub reset --hard &&
git -C super/dir_1/dir_2/sub clean -d -f
}
+test_expect_success 'submodule setup' '
+ git config --global protocol.file.allow always
+'
+
test_expect_success 'submodule always visited' '
test_when_finished "git -C super fsmonitor--daemon stop; \
rm -rf super; \
@@ -862,27 +871,9 @@ test_expect_success 'submodule always visited' '
# the submodule, and someone does a `git submodule absorbgitdirs`
# in the super, Git will recursively invoke `git submodule--helper`
# to do the work and this may try to read the index. This will
-# try to start the daemon in the submodule *and* pass (either
-# directly or via inheritance) the `--super-prefix` arg to the
-# `git fsmonitor--daemon start` command inside the submodule.
-# This causes a warning because fsmonitor--daemon does take that
-# global arg (see the table in git.c)
-#
-# This causes a warning when trying to start the daemon that is
-# somewhat confusing. It does not seem to hurt anything because
-# the fsmonitor code maps the query failure into a trivial response
-# and does the work anyway.
-#
-# It would be nice to silence the warning, however.
-
-have_t2_error_event () {
- log=$1
- msg="fsmonitor--daemon doesnQt support --super-prefix" &&
+# try to start the daemon in the submodule.
- tr '\047' Q <$1 | grep -e "$msg"
-}
-
-test_expect_success "stray submodule super-prefix warning" '
+test_expect_success "submodule absorbgitdirs implicitly starts daemon" '
test_when_finished "rm -rf super; \
rm -rf sub; \
rm super-sub.trace" &&
@@ -900,21 +891,31 @@ test_expect_success "stray submodule super-prefix warning" '
test_path_is_dir super/dir_1/dir_2/sub/.git &&
+ cwd="$(cd super && pwd)" &&
+ cat >expect <<-EOF &&
+ Migrating git directory of '\''dir_1/dir_2/sub'\'' from
+ '\''$cwd/dir_1/dir_2/sub/.git'\'' to
+ '\''$cwd/.git/modules/dir_1/dir_2/sub'\''
+ EOF
GIT_TRACE2_EVENT="$PWD/super-sub.trace" \
- git -C super submodule absorbgitdirs &&
+ git -C super submodule absorbgitdirs >out 2>actual &&
+ test_cmp expect actual &&
+ test_must_be_empty out &&
- ! have_t2_error_event super-sub.trace
+ # Confirm that the trace2 log contains a record of the
+ # daemon starting.
+ test_subcommand git fsmonitor--daemon start <super-sub.trace
'
# On a case-insensitive file system, confirm that the daemon
# notices when the .git directory is moved/renamed/deleted
-# regardless of how it is spelled in the the FS event.
+# regardless of how it is spelled in the FS event.
# That is, does the FS event receive the spelling of the
# operation or does it receive the spelling preserved with
# the file/directory.
#
test_expect_success CASE_INSENSITIVE_FS 'case insensitive+preserving' '
-# test_when_finished "stop_daemon_delete_repo test_insensitive" &&
+ test_when_finished "stop_daemon_delete_repo test_insensitive" &&
git init test_insensitive &&
@@ -926,8 +927,8 @@ test_expect_success CASE_INSENSITIVE_FS 'case insensitive+preserving' '
test_path_is_dir test_insensitive/.git &&
test_path_is_dir test_insensitive/.GIT &&
- # Rename .git using an alternate spelling to verify that that
- # daemon detects it and automatically shuts down.
+ # Rename .git using an alternate spelling to verify that
+ # the daemon detects it and automatically shuts down.
mv test_insensitive/.GIT test_insensitive/.FOO &&
# See [1] above.
@@ -939,9 +940,9 @@ test_expect_success CASE_INSENSITIVE_FS 'case insensitive+preserving' '
# directories and files that we touched. We may or may not get a
# trailing slash on modified directories.
#
- egrep "^event: abc/?$" ./insensitive.trace &&
- egrep "^event: abc/def/?$" ./insensitive.trace &&
- egrep "^event: abc/def/xyz$" ./insensitive.trace
+ grep -E "^event: abc/?$" ./insensitive.trace &&
+ grep -E "^event: abc/def/?$" ./insensitive.trace &&
+ grep -E "^event: abc/def/xyz$" ./insensitive.trace
'
# The variable "unicode_debug" is defined in the following library
@@ -977,26 +978,286 @@ test_expect_success !UNICODE_COMPOSITION_SENSITIVE 'Unicode nfc/nfd' '
mkdir test_unicode/nfd &&
mkdir test_unicode/nfd/d_${utf8_nfd} &&
- git -C test_unicode fsmonitor--daemon stop &&
+ test-tool -C test_unicode fsmonitor-client query --token 0 &&
if test_have_prereq UNICODE_NFC_PRESERVED
then
# We should have seen NFC event from OS.
# We should not have synthesized an NFD event.
- egrep "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace &&
- egrep -v "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace
+ grep -E "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace &&
+ grep -E -v "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace
else
# We should have seen NFD event from OS.
# We should have synthesized an NFC event.
- egrep "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace &&
- egrep "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace
+ grep -E "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace &&
+ grep -E "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace
fi &&
# We assume UNICODE_NFD_PRESERVED.
# We should have seen explicit NFD from OS.
# We should have synthesized an NFC event.
- egrep "^event: nfd/d_${utf8_nfd}/?$" ./unicode.trace &&
- egrep "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
+ grep -E "^event: nfd/d_${utf8_nfd}/?$" ./unicode.trace &&
+ grep -E "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
+'
+
+test_expect_success 'split-index and FSMonitor work well together' '
+ git init split-index &&
+ test_when_finished "git -C \"$PWD/split-index\" \
+ fsmonitor--daemon stop" &&
+ (
+ cd split-index &&
+ git config core.splitIndex true &&
+ # force split-index in most cases
+ git config splitIndex.maxPercentChange 99 &&
+ git config core.fsmonitor true &&
+
+ # Create the following commit topology:
+ #
+ # * merge three
+ # |\
+ # | * three
+ # * | merge two
+ # |\|
+ # | * two
+ # * | one
+ # |/
+ # * 5a5efd7 initial
+
+ test_commit initial &&
+ test_commit two &&
+ test_commit three &&
+ git reset --hard initial &&
+ test_commit one &&
+ test_tick &&
+ git merge two &&
+ test_tick &&
+ git merge three &&
+
+ git rebase --force-rebase -r one
+ )
+'
+
+# The FSMonitor daemon reports the OBSERVED pathname of modified files
+# and thus contains the OBSERVED spelling on case-insensitive file
+# systems. The daemon does not (and should not) load the .git/index
+# file and therefore does not know the expected case-spelling. Since
+# it is possible for the user to create files/subdirectories with the
+# incorrect case, a modified file event for a tracked will not have
+# the EXPECTED case. This can cause `index_name_pos()` to incorrectly
+# report that the file is untracked. This causes the client to fail to
+# mark the file as possibly dirty (keeping the CE_FSMONITOR_VALID bit
+# set) so that `git status` will avoid inspecting it and thus not
+# present in the status output.
+#
+# The setup is a little contrived.
+#
+test_expect_success CASE_INSENSITIVE_FS 'fsmonitor subdir case wrong on disk' '
+ test_when_finished "stop_daemon_delete_repo subdir_case_wrong" &&
+
+ git init subdir_case_wrong &&
+ (
+ cd subdir_case_wrong &&
+ echo x >AAA &&
+ echo x >BBB &&
+
+ mkdir dir1 &&
+ echo x >dir1/file1 &&
+ mkdir dir1/dir2 &&
+ echo x >dir1/dir2/file2 &&
+ mkdir dir1/dir2/dir3 &&
+ echo x >dir1/dir2/dir3/file3 &&
+
+ echo x >yyy &&
+ echo x >zzz &&
+ git add . &&
+ git commit -m "data" &&
+
+ # This will cause "dir1/" and everything under it
+ # to be deleted.
+ git sparse-checkout set --cone --sparse-index &&
+
+ # Create dir2 with the wrong case and then let Git
+ # repopulate dir3 -- it will not correct the spelling
+ # of dir2.
+ mkdir dir1 &&
+ mkdir dir1/DIR2 &&
+ git sparse-checkout add dir1/dir2/dir3
+ ) &&
+
+ start_daemon -C subdir_case_wrong --tf "$PWD/subdir_case_wrong.trace" &&
+
+ # Enable FSMonitor in the client. Run enough commands for
+ # the .git/index to sync up with the daemon with everything
+ # marked clean.
+ git -C subdir_case_wrong config core.fsmonitor true &&
+ git -C subdir_case_wrong update-index --fsmonitor &&
+ git -C subdir_case_wrong status &&
+
+ # Make some files dirty so that FSMonitor gets FSEvents for
+ # each of them.
+ echo xx >>subdir_case_wrong/AAA &&
+ echo xx >>subdir_case_wrong/dir1/DIR2/dir3/file3 &&
+ echo xx >>subdir_case_wrong/zzz &&
+
+ GIT_TRACE_FSMONITOR="$PWD/subdir_case_wrong.log" \
+ git -C subdir_case_wrong --no-optional-locks status --short \
+ >"$PWD/subdir_case_wrong.out" &&
+
+ # "git status" should have gotten file events for each of
+ # the 3 files.
+ #
+ # "dir2" should be in the observed case on disk.
+ grep "fsmonitor_refresh_callback" \
+ <"$PWD/subdir_case_wrong.log" \
+ >"$PWD/subdir_case_wrong.log1" &&
+
+ grep -q "AAA.*pos 0" "$PWD/subdir_case_wrong.log1" &&
+ grep -q "zzz.*pos 6" "$PWD/subdir_case_wrong.log1" &&
+
+ grep -q "dir1/DIR2/dir3/file3.*pos -3" "$PWD/subdir_case_wrong.log1" &&
+
+ # Verify that we get a mapping event to correct the case.
+ grep -q "MAP:.*dir1/DIR2/dir3/file3.*dir1/dir2/dir3/file3" \
+ "$PWD/subdir_case_wrong.log1" &&
+
+ # The refresh-callbacks should have caused "git status" to clear
+ # the CE_FSMONITOR_VALID bit on each of those files and caused
+ # the worktree scan to visit them and mark them as modified.
+ grep -q " M AAA" "$PWD/subdir_case_wrong.out" &&
+ grep -q " M zzz" "$PWD/subdir_case_wrong.out" &&
+ grep -q " M dir1/dir2/dir3/file3" "$PWD/subdir_case_wrong.out"
+'
+
+test_expect_success CASE_INSENSITIVE_FS 'fsmonitor file case wrong on disk' '
+ test_when_finished "stop_daemon_delete_repo file_case_wrong" &&
+
+ git init file_case_wrong &&
+ (
+ cd file_case_wrong &&
+ echo x >AAA &&
+ echo x >BBB &&
+
+ mkdir dir1 &&
+ mkdir dir1/dir2 &&
+ mkdir dir1/dir2/dir3 &&
+ echo x >dir1/dir2/dir3/FILE-3-B &&
+ echo x >dir1/dir2/dir3/XXXX-3-X &&
+ echo x >dir1/dir2/dir3/file-3-a &&
+ echo x >dir1/dir2/dir3/yyyy-3-y &&
+ mkdir dir1/dir2/dir4 &&
+ echo x >dir1/dir2/dir4/FILE-4-A &&
+ echo x >dir1/dir2/dir4/XXXX-4-X &&
+ echo x >dir1/dir2/dir4/file-4-b &&
+ echo x >dir1/dir2/dir4/yyyy-4-y &&
+
+ echo x >yyy &&
+ echo x >zzz &&
+ git add . &&
+ git commit -m "data"
+ ) &&
+
+ start_daemon -C file_case_wrong --tf "$PWD/file_case_wrong.trace" &&
+
+ # Enable FSMonitor in the client. Run enough commands for
+ # the .git/index to sync up with the daemon with everything
+ # marked clean.
+ git -C file_case_wrong config core.fsmonitor true &&
+ git -C file_case_wrong update-index --fsmonitor &&
+ git -C file_case_wrong status &&
+
+ # Make some files dirty so that FSMonitor gets FSEvents for
+ # each of them.
+ echo xx >>file_case_wrong/AAA &&
+ echo xx >>file_case_wrong/zzz &&
+
+ # Rename some files so that FSMonitor sees a create and delete
+ # FSEvent for each. (A simple "mv foo FOO" is not portable
+ # between macOS and Windows. It works on both platforms, but makes
+ # the test messy, since (1) one platform updates "ctime" on the
+ # moved file and one does not and (2) it causes a directory event
+ # on one platform and not on the other which causes additional
+ # scanning during "git status" which causes a "H" vs "h" discrepancy
+ # in "git ls-files -f".) So old-school it and move it out of the
+ # way and copy it to the case-incorrect name so that we get fresh
+ # "ctime" and "mtime" values.
+
+ mv file_case_wrong/dir1/dir2/dir3/file-3-a file_case_wrong/dir1/dir2/dir3/ORIG &&
+ cp file_case_wrong/dir1/dir2/dir3/ORIG file_case_wrong/dir1/dir2/dir3/FILE-3-A &&
+ rm file_case_wrong/dir1/dir2/dir3/ORIG &&
+ mv file_case_wrong/dir1/dir2/dir4/FILE-4-A file_case_wrong/dir1/dir2/dir4/ORIG &&
+ cp file_case_wrong/dir1/dir2/dir4/ORIG file_case_wrong/dir1/dir2/dir4/file-4-a &&
+ rm file_case_wrong/dir1/dir2/dir4/ORIG &&
+
+ # Run status enough times to fully sync.
+ #
+ # The first instance should get the create and delete FSEvents
+ # for each pair. Status should update the index with a new FSM
+ # token (so the next invocation will not see data for these
+ # events).
+
+ GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try1.log" \
+ git -C file_case_wrong status --short \
+ >"$PWD/file_case_wrong-try1.out" &&
+ grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos -3" "$PWD/file_case_wrong-try1.log" &&
+ grep -q "fsmonitor_refresh_callback.*file-3-a.*pos 4" "$PWD/file_case_wrong-try1.log" &&
+ grep -q "fsmonitor_refresh_callback.*FILE-4-A.*pos 6" "$PWD/file_case_wrong-try1.log" &&
+ grep -q "fsmonitor_refresh_callback.*file-4-a.*pos -9" "$PWD/file_case_wrong-try1.log" &&
+
+ # FSM refresh will have invalidated the FSM bit and cause a regular
+ # (real) scan of these tracked files, so they should have "H" status.
+ # (We will not see a "h" status until the next refresh (on the next
+ # command).)
+
+ git -C file_case_wrong ls-files -f >"$PWD/file_case_wrong-lsf1.out" &&
+ grep -q "H dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-lsf1.out" &&
+ grep -q "H dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-lsf1.out" &&
+
+
+ # Try the status again. We assume that the above status command
+ # advanced the token so that the next one will not see those events.
+
+ GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try2.log" \
+ git -C file_case_wrong status --short \
+ >"$PWD/file_case_wrong-try2.out" &&
+ ! grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos" "$PWD/file_case_wrong-try2.log" &&
+ ! grep -q "fsmonitor_refresh_callback.*file-3-a.*pos" "$PWD/file_case_wrong-try2.log" &&
+ ! grep -q "fsmonitor_refresh_callback.*FILE-4-A.*pos" "$PWD/file_case_wrong-try2.log" &&
+ ! grep -q "fsmonitor_refresh_callback.*file-4-a.*pos" "$PWD/file_case_wrong-try2.log" &&
+
+ # FSM refresh saw nothing, so it will mark all files as valid,
+ # so they should now have "h" status.
+
+ git -C file_case_wrong ls-files -f >"$PWD/file_case_wrong-lsf2.out" &&
+ grep -q "h dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-lsf2.out" &&
+ grep -q "h dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-lsf2.out" &&
+
+
+ # We now have files with clean content, but with case-incorrect
+ # file names. Modify them to see if status properly reports
+ # them.
+
+ echo xx >>file_case_wrong/dir1/dir2/dir3/FILE-3-A &&
+ echo xx >>file_case_wrong/dir1/dir2/dir4/file-4-a &&
+
+ GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try3.log" \
+ git -C file_case_wrong --no-optional-locks status --short \
+ >"$PWD/file_case_wrong-try3.out" &&
+
+ # Verify that we get a mapping event to correct the case.
+ grep -q "fsmonitor_refresh_callback MAP:.*dir1/dir2/dir3/FILE-3-A.*dir1/dir2/dir3/file-3-a" \
+ "$PWD/file_case_wrong-try3.log" &&
+ grep -q "fsmonitor_refresh_callback MAP:.*dir1/dir2/dir4/file-4-a.*dir1/dir2/dir4/FILE-4-A" \
+ "$PWD/file_case_wrong-try3.log" &&
+
+ # FSEvents are in observed case.
+ grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos -3" "$PWD/file_case_wrong-try3.log" &&
+ grep -q "fsmonitor_refresh_callback.*file-4-a.*pos -9" "$PWD/file_case_wrong-try3.log" &&
+
+ # The refresh-callbacks should have caused "git status" to clear
+ # the CE_FSMONITOR_VALID bit on each of those files and caused
+ # the worktree scan to visit them and mark them as modified.
+ grep -q " M dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-try3.out" &&
+ grep -q " M dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-try3.out"
'
test_done