@@ -198,37 +198,75 @@ int fsmonitor_is_trivial_response(const struct strbuf *query_result)
198
198
static void fsmonitor_refresh_callback (struct index_state * istate , char * name )
199
199
{
200
200
int i , len = strlen (name );
201
+ int pos = index_name_pos (istate , name , len );
202
+
203
+ trace_printf_key (& trace_fsmonitor ,
204
+ "fsmonitor_refresh_callback '%s' (pos %d)" ,
205
+ name , pos );
206
+
201
207
if (name [len - 1 ] == '/' ) {
202
- const char * rel ;
203
- int pos = index_name_pos (istate , name , len );
208
+ /*
209
+ * The daemon can decorate directory events, such as
210
+ * moves or renames, with a trailing slash if the OS
211
+ * FS Event contains sufficient information, such as
212
+ * MacOS.
213
+ *
214
+ * Use this to invalidate the entire cone under that
215
+ * directory.
216
+ *
217
+ * We do not expect an exact match because the index
218
+ * does not normally contain directory entries, so we
219
+ * start at the insertion point and scan.
220
+ */
204
221
if (pos < 0 )
205
222
pos = - pos - 1 ;
206
223
207
224
/* Mark all entries for the folder invalid */
208
225
for (i = pos ; i < istate -> cache_nr ; i ++ ) {
209
226
if (!starts_with (istate -> cache [i ]-> name , name ))
210
227
break ;
211
- /* Only mark the immediate children in the folder */
212
- rel = istate -> cache [i ]-> name + len ;
213
- if (!strchr (rel , '/' ))
214
- istate -> cache [i ]-> ce_flags &= ~CE_FSMONITOR_VALID ;
228
+ istate -> cache [i ]-> ce_flags &= ~CE_FSMONITOR_VALID ;
215
229
}
216
- /* Need to remove the / from the path for the untracked cache */
230
+
231
+ /*
232
+ * We need to remove the traling "/" from the path
233
+ * for the untracked cache.
234
+ */
217
235
name [len - 1 ] = '\0' ;
236
+ } else if (pos >= 0 ) {
237
+ /*
238
+ * We have an exact match for this path and can just
239
+ * invalidate it.
240
+ */
241
+ istate -> cache [pos ]-> ce_flags &= ~CE_FSMONITOR_VALID ;
218
242
} else {
219
- int pos = index_name_pos (istate , name , len );
243
+ /*
244
+ * The path is not a tracked file -or- it is a
245
+ * directory event on a platform that cannot
246
+ * distinguish between file and directory events in
247
+ * the event handler, such as Windows.
248
+ *
249
+ * Scan as if it is a directory and invalidate the
250
+ * cone under it. (But remember to ignore items
251
+ * between "name" and "name/", such as "name-" and
252
+ * "name.".
253
+ */
254
+ pos = - pos - 1 ;
220
255
221
- if (pos >= 0 ) {
222
- struct cache_entry * ce = istate -> cache [pos ];
223
- ce -> ce_flags &= ~CE_FSMONITOR_VALID ;
256
+ for (i = pos ; i < istate -> cache_nr ; i ++ ) {
257
+ if (!starts_with (istate -> cache [i ]-> name , name ))
258
+ break ;
259
+ if ((unsigned char )istate -> cache [i ]-> name [len ] > '/' )
260
+ break ;
261
+ if (istate -> cache [i ]-> name [len ] == '/' )
262
+ istate -> cache [i ]-> ce_flags &= ~CE_FSMONITOR_VALID ;
224
263
}
225
264
}
226
265
227
266
/*
228
267
* Mark the untracked cache dirty even if it wasn't found in the index
229
268
* as it could be a new untracked file.
230
269
*/
231
- trace_printf_key (& trace_fsmonitor , "fsmonitor_refresh_callback '%s'" , name );
232
270
untracked_cache_invalidate_path (istate , name , 0 );
233
271
}
234
272
0 commit comments