@@ -1037,4 +1037,221 @@ test_expect_success 'split-index and FSMonitor work well together' '
1037
1037
)
1038
1038
'
1039
1039
1040
+ # The FSMonitor daemon reports the OBSERVED pathname of modified files
1041
+ # and thus contains the OBSERVED spelling on case-insensitive file
1042
+ # systems. The daemon does not (and should not) load the .git/index
1043
+ # file and therefore does not know the expected case-spelling. Since
1044
+ # it is possible for the user to create files/subdirectories with the
1045
+ # incorrect case, a modified file event for a tracked will not have
1046
+ # the EXPECTED case. This can cause `index_name_pos()` to incorrectly
1047
+ # report that the file is untracked. This causes the client to fail to
1048
+ # mark the file as possibly dirty (keeping the CE_FSMONITOR_VALID bit
1049
+ # set) so that `git status` will avoid inspecting it and thus not
1050
+ # present in the status output.
1051
+ #
1052
+ # The setup is a little contrived.
1053
+ #
1054
+ test_expect_failure CASE_INSENSITIVE_FS ' fsmonitor subdir case wrong on disk' '
1055
+ test_when_finished "stop_daemon_delete_repo subdir_case_wrong" &&
1056
+
1057
+ git init subdir_case_wrong &&
1058
+ (
1059
+ cd subdir_case_wrong &&
1060
+ echo x >AAA &&
1061
+ echo x >BBB &&
1062
+
1063
+ mkdir dir1 &&
1064
+ echo x >dir1/file1 &&
1065
+ mkdir dir1/dir2 &&
1066
+ echo x >dir1/dir2/file2 &&
1067
+ mkdir dir1/dir2/dir3 &&
1068
+ echo x >dir1/dir2/dir3/file3 &&
1069
+
1070
+ echo x >yyy &&
1071
+ echo x >zzz &&
1072
+ git add . &&
1073
+ git commit -m "data" &&
1074
+
1075
+ # This will cause "dir1/" and everything under it
1076
+ # to be deleted.
1077
+ git sparse-checkout set --cone --sparse-index &&
1078
+
1079
+ # Create dir2 with the wrong case and then let Git
1080
+ # repopulate dir3 -- it will not correct the spelling
1081
+ # of dir2.
1082
+ mkdir dir1 &&
1083
+ mkdir dir1/DIR2 &&
1084
+ git sparse-checkout add dir1/dir2/dir3
1085
+ ) &&
1086
+
1087
+ start_daemon -C subdir_case_wrong --tf "$PWD/subdir_case_wrong.trace" &&
1088
+
1089
+ # Enable FSMonitor in the client. Run enough commands for
1090
+ # the .git/index to sync up with the daemon with everything
1091
+ # marked clean.
1092
+ git -C subdir_case_wrong config core.fsmonitor true &&
1093
+ git -C subdir_case_wrong update-index --fsmonitor &&
1094
+ git -C subdir_case_wrong status &&
1095
+
1096
+ # Make some files dirty so that FSMonitor gets FSEvents for
1097
+ # each of them.
1098
+ echo xx >>subdir_case_wrong/AAA &&
1099
+ echo xx >>subdir_case_wrong/dir1/DIR2/dir3/file3 &&
1100
+ echo xx >>subdir_case_wrong/zzz &&
1101
+
1102
+ GIT_TRACE_FSMONITOR="$PWD/subdir_case_wrong.log" \
1103
+ git -C subdir_case_wrong --no-optional-locks status --short \
1104
+ >"$PWD/subdir_case_wrong.out" &&
1105
+
1106
+ # "git status" should have gotten file events for each of
1107
+ # the 3 files.
1108
+ #
1109
+ # "dir2" should be in the observed case on disk.
1110
+ grep "fsmonitor_refresh_callback" \
1111
+ <"$PWD/subdir_case_wrong.log" \
1112
+ >"$PWD/subdir_case_wrong.log1" &&
1113
+
1114
+ grep -q "AAA.*pos 0" "$PWD/subdir_case_wrong.log1" &&
1115
+ grep -q "zzz.*pos 6" "$PWD/subdir_case_wrong.log1" &&
1116
+
1117
+ grep -q "dir1/DIR2/dir3/file3.*pos -3" "$PWD/subdir_case_wrong.log1" &&
1118
+
1119
+ # The refresh-callbacks should have caused "git status" to clear
1120
+ # the CE_FSMONITOR_VALID bit on each of those files and caused
1121
+ # the worktree scan to visit them and mark them as modified.
1122
+ grep -q " M AAA" "$PWD/subdir_case_wrong.out" &&
1123
+ grep -q " M zzz" "$PWD/subdir_case_wrong.out" &&
1124
+
1125
+ # Expect Breakage: with the case confusion, the "(pos -3)" causes
1126
+ # the client to not clear the CE_FSMONITOR_VALID bit and therefore
1127
+ # status will not rescan the file and therefore not report it as dirty.
1128
+ grep -q " M dir1/dir2/dir3/file3" "$PWD/subdir_case_wrong.out"
1129
+ '
1130
+
1131
+ test_expect_failure CASE_INSENSITIVE_FS ' fsmonitor file case wrong on disk' '
1132
+ test_when_finished "stop_daemon_delete_repo file_case_wrong" &&
1133
+
1134
+ git init file_case_wrong &&
1135
+ (
1136
+ cd file_case_wrong &&
1137
+ echo x >AAA &&
1138
+ echo x >BBB &&
1139
+
1140
+ mkdir dir1 &&
1141
+ mkdir dir1/dir2 &&
1142
+ mkdir dir1/dir2/dir3 &&
1143
+ echo x >dir1/dir2/dir3/FILE-3-B &&
1144
+ echo x >dir1/dir2/dir3/XXXX-3-X &&
1145
+ echo x >dir1/dir2/dir3/file-3-a &&
1146
+ echo x >dir1/dir2/dir3/yyyy-3-y &&
1147
+ mkdir dir1/dir2/dir4 &&
1148
+ echo x >dir1/dir2/dir4/FILE-4-A &&
1149
+ echo x >dir1/dir2/dir4/XXXX-4-X &&
1150
+ echo x >dir1/dir2/dir4/file-4-b &&
1151
+ echo x >dir1/dir2/dir4/yyyy-4-y &&
1152
+
1153
+ echo x >yyy &&
1154
+ echo x >zzz &&
1155
+ git add . &&
1156
+ git commit -m "data"
1157
+ ) &&
1158
+
1159
+ start_daemon -C file_case_wrong --tf "$PWD/file_case_wrong.trace" &&
1160
+
1161
+ # Enable FSMonitor in the client. Run enough commands for
1162
+ # the .git/index to sync up with the daemon with everything
1163
+ # marked clean.
1164
+ git -C file_case_wrong config core.fsmonitor true &&
1165
+ git -C file_case_wrong update-index --fsmonitor &&
1166
+ git -C file_case_wrong status &&
1167
+
1168
+ # Make some files dirty so that FSMonitor gets FSEvents for
1169
+ # each of them.
1170
+ echo xx >>file_case_wrong/AAA &&
1171
+ echo xx >>file_case_wrong/zzz &&
1172
+
1173
+ # Rename some files so that FSMonitor sees a create and delete
1174
+ # FSEvent for each. (A simple "mv foo FOO" is not portable
1175
+ # between macOS and Windows. It works on both platforms, but makes
1176
+ # the test messy, since (1) one platform updates "ctime" on the
1177
+ # moved file and one does not and (2) it causes a directory event
1178
+ # on one platform and not on the other which causes additional
1179
+ # scanning during "git status" which causes a "H" vs "h" discrepancy
1180
+ # in "git ls-files -f".) So old-school it and move it out of the
1181
+ # way and copy it to the case-incorrect name so that we get fresh
1182
+ # "ctime" and "mtime" values.
1183
+
1184
+ mv file_case_wrong/dir1/dir2/dir3/file-3-a file_case_wrong/dir1/dir2/dir3/ORIG &&
1185
+ cp file_case_wrong/dir1/dir2/dir3/ORIG file_case_wrong/dir1/dir2/dir3/FILE-3-A &&
1186
+ rm file_case_wrong/dir1/dir2/dir3/ORIG &&
1187
+ mv file_case_wrong/dir1/dir2/dir4/FILE-4-A file_case_wrong/dir1/dir2/dir4/ORIG &&
1188
+ cp file_case_wrong/dir1/dir2/dir4/ORIG file_case_wrong/dir1/dir2/dir4/file-4-a &&
1189
+ rm file_case_wrong/dir1/dir2/dir4/ORIG &&
1190
+
1191
+ # Run status enough times to fully sync.
1192
+ #
1193
+ # The first instance should get the create and delete FSEvents
1194
+ # for each pair. Status should update the index with a new FSM
1195
+ # token (so the next invocation will not see data for these
1196
+ # events).
1197
+
1198
+ GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try1.log" \
1199
+ git -C file_case_wrong status --short \
1200
+ >"$PWD/file_case_wrong-try1.out" &&
1201
+ grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos -3" "$PWD/file_case_wrong-try1.log" &&
1202
+ grep -q "fsmonitor_refresh_callback.*file-3-a.*pos 4" "$PWD/file_case_wrong-try1.log" &&
1203
+ grep -q "fsmonitor_refresh_callback.*FILE-4-A.*pos 6" "$PWD/file_case_wrong-try1.log" &&
1204
+ grep -q "fsmonitor_refresh_callback.*file-4-a.*pos -9" "$PWD/file_case_wrong-try1.log" &&
1205
+
1206
+ # FSM refresh will have invalidated the FSM bit and cause a regular
1207
+ # (real) scan of these tracked files, so they should have "H" status.
1208
+ # (We will not see a "h" status until the next refresh (on the next
1209
+ # command).)
1210
+
1211
+ git -C file_case_wrong ls-files -f >"$PWD/file_case_wrong-lsf1.out" &&
1212
+ grep -q "H dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-lsf1.out" &&
1213
+ grep -q "H dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-lsf1.out" &&
1214
+
1215
+
1216
+ # Try the status again. We assume that the above status command
1217
+ # advanced the token so that the next one will not see those events.
1218
+
1219
+ GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try2.log" \
1220
+ git -C file_case_wrong status --short \
1221
+ >"$PWD/file_case_wrong-try2.out" &&
1222
+ ! grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos" "$PWD/file_case_wrong-try2.log" &&
1223
+ ! grep -q "fsmonitor_refresh_callback.*file-3-a.*pos" "$PWD/file_case_wrong-try2.log" &&
1224
+ ! grep -q "fsmonitor_refresh_callback.*FILE-4-A.*pos" "$PWD/file_case_wrong-try2.log" &&
1225
+ ! grep -q "fsmonitor_refresh_callback.*file-4-a.*pos" "$PWD/file_case_wrong-try2.log" &&
1226
+
1227
+ # FSM refresh saw nothing, so it will mark all files as valid,
1228
+ # so they should now have "h" status.
1229
+
1230
+ git -C file_case_wrong ls-files -f >"$PWD/file_case_wrong-lsf2.out" &&
1231
+ grep -q "h dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-lsf2.out" &&
1232
+ grep -q "h dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-lsf2.out" &&
1233
+
1234
+
1235
+ # We now have files with clean content, but with case-incorrect
1236
+ # file names. Modify them to see if status properly reports
1237
+ # them.
1238
+
1239
+ echo xx >>file_case_wrong/dir1/dir2/dir3/FILE-3-A &&
1240
+ echo xx >>file_case_wrong/dir1/dir2/dir4/file-4-a &&
1241
+
1242
+ GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try3.log" \
1243
+ git -C file_case_wrong --no-optional-locks status --short \
1244
+ >"$PWD/file_case_wrong-try3.out" &&
1245
+ # FSEvents are in observed case.
1246
+ grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos -3" "$PWD/file_case_wrong-try3.log" &&
1247
+ grep -q "fsmonitor_refresh_callback.*file-4-a.*pos -9" "$PWD/file_case_wrong-try3.log" &&
1248
+
1249
+ # Expect Breakage: with the case confusion, the "(pos-3)" and
1250
+ # "(pos -9)" causes the client to not clear the CE_FSMONITOR_VALID
1251
+ # bit and therefore status will not rescan the files and therefore
1252
+ # not report them as dirty.
1253
+ grep -q " M dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-try3.out" &&
1254
+ grep -q " M dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-try3.out"
1255
+ '
1256
+
1040
1257
test_done
0 commit comments