Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | #define USE_THE_REPOSITORY_VARIABLE  | 
2  |  |  | 
3  |  | #include "git-compat-util.h"  | 
4  |  | #include "config.h"  | 
5  |  | #include "dir.h"  | 
6  |  | #include "environment.h"  | 
7  |  | #include "ewah/ewok.h"  | 
8  |  | #include "fsmonitor.h"  | 
9  |  | #include "fsmonitor-ipc.h"  | 
10  |  | #include "name-hash.h"  | 
11  |  | #include "run-command.h"  | 
12  |  | #include "strbuf.h"  | 
13  |  | #include "trace2.h"  | 
14  |  |  | 
15  | 0  | #define INDEX_EXTENSION_VERSION1  (1)  | 
16  | 0  | #define INDEX_EXTENSION_VERSION2  (2)  | 
17  | 0  | #define HOOK_INTERFACE_VERSION1   (1)  | 
18  | 0  | #define HOOK_INTERFACE_VERSION2   (2)  | 
19  |  |  | 
20  |  | struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);  | 
21  |  |  | 
22  |  | static void assert_index_minimum(struct index_state *istate, size_t pos)  | 
23  | 0  | { | 
24  | 0  |   if (pos > istate->cache_nr)  | 
25  | 0  |     BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)", | 
26  | 0  |         (uintmax_t)pos, istate->cache_nr);  | 
27  | 0  | }  | 
28  |  |  | 
29  |  | static void fsmonitor_ewah_callback(size_t pos, void *is)  | 
30  | 0  | { | 
31  | 0  |   struct index_state *istate = (struct index_state *)is;  | 
32  | 0  |   struct cache_entry *ce;  | 
33  |  | 
  | 
34  | 0  |   assert_index_minimum(istate, pos + 1);  | 
35  |  | 
  | 
36  | 0  |   ce = istate->cache[pos];  | 
37  | 0  |   ce->ce_flags &= ~CE_FSMONITOR_VALID;  | 
38  | 0  | }  | 
39  |  |  | 
40  |  | static int fsmonitor_hook_version(void)  | 
41  | 0  | { | 
42  | 0  |   int hook_version;  | 
43  |  | 
  | 
44  | 0  |   if (git_config_get_int("core.fsmonitorhookversion", &hook_version)) | 
45  | 0  |     return -1;  | 
46  |  |  | 
47  | 0  |   if (hook_version == HOOK_INTERFACE_VERSION1 ||  | 
48  | 0  |       hook_version == HOOK_INTERFACE_VERSION2)  | 
49  | 0  |     return hook_version;  | 
50  |  |  | 
51  | 0  |   warning("Invalid hook version '%i' in core.fsmonitorhookversion. " | 
52  | 0  |     "Must be 1 or 2.", hook_version);  | 
53  | 0  |   return -1;  | 
54  | 0  | }  | 
55  |  |  | 
56  |  | int read_fsmonitor_extension(struct index_state *istate, const void *data,  | 
57  |  |   unsigned long sz)  | 
58  | 0  | { | 
59  | 0  |   const char *index = data;  | 
60  | 0  |   uint32_t hdr_version;  | 
61  | 0  |   uint32_t ewah_size;  | 
62  | 0  |   struct ewah_bitmap *fsmonitor_dirty;  | 
63  | 0  |   int ret;  | 
64  | 0  |   uint64_t timestamp;  | 
65  | 0  |   struct strbuf last_update = STRBUF_INIT;  | 
66  |  | 
  | 
67  | 0  |   if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))  | 
68  | 0  |     return error("corrupt fsmonitor extension (too short)"); | 
69  |  |  | 
70  | 0  |   hdr_version = get_be32(index);  | 
71  | 0  |   index += sizeof(uint32_t);  | 
72  | 0  |   if (hdr_version == INDEX_EXTENSION_VERSION1) { | 
73  | 0  |     timestamp = get_be64(index);  | 
74  | 0  |     strbuf_addf(&last_update, "%"PRIu64"", timestamp);  | 
75  | 0  |     index += sizeof(uint64_t);  | 
76  | 0  |   } else if (hdr_version == INDEX_EXTENSION_VERSION2) { | 
77  | 0  |     strbuf_addstr(&last_update, index);  | 
78  | 0  |     index += last_update.len + 1;  | 
79  | 0  |   } else { | 
80  | 0  |     return error("bad fsmonitor version %d", hdr_version); | 
81  | 0  |   }  | 
82  |  |  | 
83  | 0  |   istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);  | 
84  |  | 
  | 
85  | 0  |   ewah_size = get_be32(index);  | 
86  | 0  |   index += sizeof(uint32_t);  | 
87  |  | 
  | 
88  | 0  |   fsmonitor_dirty = ewah_new();  | 
89  | 0  |   ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);  | 
90  | 0  |   if (ret != ewah_size) { | 
91  | 0  |     ewah_free(fsmonitor_dirty);  | 
92  | 0  |     return error("failed to parse ewah bitmap reading fsmonitor index extension"); | 
93  | 0  |   }  | 
94  | 0  |   istate->fsmonitor_dirty = fsmonitor_dirty;  | 
95  |  | 
  | 
96  | 0  |   if (!istate->split_index)  | 
97  | 0  |     assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);  | 
98  |  | 
  | 
99  | 0  |   trace2_data_string("index", NULL, "extension/fsmn/read/token", | 
100  | 0  |          istate->fsmonitor_last_update);  | 
101  | 0  |   trace_printf_key(&trace_fsmonitor,  | 
102  | 0  |        "read fsmonitor extension successful '%s'",  | 
103  | 0  |        istate->fsmonitor_last_update);  | 
104  | 0  |   return 0;  | 
105  | 0  | }  | 
106  |  |  | 
107  |  | void fill_fsmonitor_bitmap(struct index_state *istate)  | 
108  | 0  | { | 
109  | 0  |   unsigned int i, skipped = 0;  | 
110  | 0  |   istate->fsmonitor_dirty = ewah_new();  | 
111  | 0  |   for (i = 0; i < istate->cache_nr; i++) { | 
112  | 0  |     if (istate->cache[i]->ce_flags & CE_REMOVE)  | 
113  | 0  |       skipped++;  | 
114  | 0  |     else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))  | 
115  | 0  |       ewah_set(istate->fsmonitor_dirty, i - skipped);  | 
116  | 0  |   }  | 
117  | 0  | }  | 
118  |  |  | 
119  |  | void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)  | 
120  | 0  | { | 
121  | 0  |   uint32_t hdr_version;  | 
122  | 0  |   uint32_t ewah_start;  | 
123  | 0  |   uint32_t ewah_size = 0;  | 
124  | 0  |   int fixup = 0;  | 
125  |  | 
  | 
126  | 0  |   if (!istate->split_index)  | 
127  | 0  |     assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);  | 
128  |  | 
  | 
129  | 0  |   put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);  | 
130  | 0  |   strbuf_add(sb, &hdr_version, sizeof(uint32_t));  | 
131  |  | 
  | 
132  | 0  |   strbuf_addstr(sb, istate->fsmonitor_last_update);  | 
133  | 0  |   strbuf_addch(sb, 0); /* Want to keep a NUL */  | 
134  |  | 
  | 
135  | 0  |   fixup = sb->len;  | 
136  | 0  |   strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */  | 
137  |  | 
  | 
138  | 0  |   ewah_start = sb->len;  | 
139  | 0  |   ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);  | 
140  | 0  |   ewah_free(istate->fsmonitor_dirty);  | 
141  | 0  |   istate->fsmonitor_dirty = NULL;  | 
142  |  |  | 
143  |  |   /* fix up size field */  | 
144  | 0  |   put_be32(&ewah_size, sb->len - ewah_start);  | 
145  | 0  |   memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));  | 
146  |  | 
  | 
147  | 0  |   trace2_data_string("index", NULL, "extension/fsmn/write/token", | 
148  | 0  |          istate->fsmonitor_last_update);  | 
149  | 0  |   trace_printf_key(&trace_fsmonitor,  | 
150  | 0  |        "write fsmonitor extension successful '%s'",  | 
151  | 0  |        istate->fsmonitor_last_update);  | 
152  | 0  | }  | 
153  |  |  | 
154  |  | /*  | 
155  |  |  * Call the query-fsmonitor hook passing the last update token of the saved results.  | 
156  |  |  */  | 
157  |  | static int query_fsmonitor_hook(struct repository *r,  | 
158  |  |         int version,  | 
159  |  |         const char *last_update,  | 
160  |  |         struct strbuf *query_result)  | 
161  | 0  | { | 
162  | 0  |   struct child_process cp = CHILD_PROCESS_INIT;  | 
163  | 0  |   int result;  | 
164  |  | 
  | 
165  | 0  |   if (fsm_settings__get_mode(r) != FSMONITOR_MODE_HOOK)  | 
166  | 0  |     return -1;  | 
167  |  |  | 
168  | 0  |   strvec_push(&cp.args, fsm_settings__get_hook_path(r));  | 
169  | 0  |   strvec_pushf(&cp.args, "%d", version);  | 
170  | 0  |   strvec_pushf(&cp.args, "%s", last_update);  | 
171  | 0  |   cp.use_shell = 1;  | 
172  | 0  |   cp.dir = get_git_work_tree();  | 
173  |  | 
  | 
174  | 0  |   trace2_region_enter("fsm_hook", "query", NULL); | 
175  |  | 
  | 
176  | 0  |   result = capture_command(&cp, query_result, 1024);  | 
177  |  | 
  | 
178  | 0  |   if (result)  | 
179  | 0  |     trace2_data_intmax("fsm_hook", NULL, "query/failed", result); | 
180  | 0  |   else  | 
181  | 0  |     trace2_data_intmax("fsm_hook", NULL, "query/response-length", | 
182  | 0  |            query_result->len);  | 
183  |  | 
  | 
184  | 0  |   trace2_region_leave("fsm_hook", "query", NULL); | 
185  |  | 
  | 
186  | 0  |   return result;  | 
187  | 0  | }  | 
188  |  |  | 
189  |  | /*  | 
190  |  |  * Invalidate the FSM bit on this CE.  This is like mark_fsmonitor_invalid()  | 
191  |  |  * but we've already handled the untracked-cache, so let's not repeat that  | 
192  |  |  * work.  This also lets us have a different trace message so that we can  | 
193  |  |  * see everything that was done as part of the refresh-callback.  | 
194  |  |  */  | 
195  |  | static void invalidate_ce_fsm(struct cache_entry *ce)  | 
196  | 0  | { | 
197  | 0  |   if (ce->ce_flags & CE_FSMONITOR_VALID) { | 
198  | 0  |     trace_printf_key(&trace_fsmonitor,  | 
199  | 0  |          "fsmonitor_refresh_callback INV: '%s'",  | 
200  | 0  |          ce->name);  | 
201  | 0  |     ce->ce_flags &= ~CE_FSMONITOR_VALID;  | 
202  | 0  |   }  | 
203  | 0  | }  | 
204  |  |  | 
205  |  | static size_t handle_path_with_trailing_slash(  | 
206  |  |   struct index_state *istate, const char *name, int pos);  | 
207  |  |  | 
208  |  | /*  | 
209  |  |  * Use the name-hash to do a case-insensitive cache-entry lookup with  | 
210  |  |  * the pathname and invalidate the cache-entry.  | 
211  |  |  *  | 
212  |  |  * Returns the number of cache-entries that we invalidated.  | 
213  |  |  */  | 
214  |  | static size_t handle_using_name_hash_icase(  | 
215  |  |   struct index_state *istate, const char *name)  | 
216  | 0  | { | 
217  | 0  |   struct cache_entry *ce = NULL;  | 
218  |  | 
  | 
219  | 0  |   ce = index_file_exists(istate, name, strlen(name), 1);  | 
220  | 0  |   if (!ce)  | 
221  | 0  |     return 0;  | 
222  |  |  | 
223  |  |   /*  | 
224  |  |    * A case-insensitive search in the name-hash using the  | 
225  |  |    * observed pathname found a cache-entry, so the observed path  | 
226  |  |    * is case-incorrect.  Invalidate the cache-entry and use the  | 
227  |  |    * correct spelling from the cache-entry to invalidate the  | 
228  |  |    * untracked-cache.  Since we now have sparse-directories in  | 
229  |  |    * the index, the observed pathname may represent a regular  | 
230  |  |    * file or a sparse-index directory.  | 
231  |  |    *  | 
232  |  |    * Note that we should not have seen FSEvents for a  | 
233  |  |    * sparse-index directory, but we handle it just in case.  | 
234  |  |    *  | 
235  |  |    * Either way, we know that there are not any cache-entries for  | 
236  |  |    * children inside the cone of the directory, so we don't need to  | 
237  |  |    * do the usual scan.  | 
238  |  |    */  | 
239  | 0  |   trace_printf_key(&trace_fsmonitor,  | 
240  | 0  |        "fsmonitor_refresh_callback MAP: '%s' '%s'",  | 
241  | 0  |        name, ce->name);  | 
242  |  |  | 
243  |  |   /*  | 
244  |  |    * NEEDSWORK: We used the name-hash to find the correct  | 
245  |  |    * case-spelling of the pathname in the cache-entry[], so  | 
246  |  |    * technically this is a tracked file or a sparse-directory.  | 
247  |  |    * It should not have any entries in the untracked-cache, so  | 
248  |  |    * we should not need to use the case-corrected spelling to  | 
249  |  |    * invalidate the the untracked-cache.  So we may not need to  | 
250  |  |    * do this.  For now, I'm going to be conservative and always  | 
251  |  |    * do it; we can revisit this later.  | 
252  |  |    */  | 
253  | 0  |   untracked_cache_invalidate_trimmed_path(istate, ce->name, 0);  | 
254  |  | 
  | 
255  | 0  |   invalidate_ce_fsm(ce);  | 
256  | 0  |   return 1;  | 
257  | 0  | }  | 
258  |  |  | 
259  |  | /*  | 
260  |  |  * Use the dir-name-hash to find the correct-case spelling of the  | 
261  |  |  * directory.  Use the canonical spelling to invalidate all of the  | 
262  |  |  * cache-entries within the matching cone.  | 
263  |  |  *  | 
264  |  |  * Returns the number of cache-entries that we invalidated.  | 
265  |  |  */  | 
266  |  | static size_t handle_using_dir_name_hash_icase(  | 
267  |  |   struct index_state *istate, const char *name)  | 
268  | 0  | { | 
269  | 0  |   struct strbuf canonical_path = STRBUF_INIT;  | 
270  | 0  |   int pos;  | 
271  | 0  |   size_t len = strlen(name);  | 
272  | 0  |   size_t nr_in_cone;  | 
273  |  | 
  | 
274  | 0  |   if (name[len - 1] == '/')  | 
275  | 0  |     len--;  | 
276  |  | 
  | 
277  | 0  |   if (!index_dir_find(istate, name, len, &canonical_path))  | 
278  | 0  |     return 0; /* name is untracked */  | 
279  |  |  | 
280  | 0  |   if (!memcmp(name, canonical_path.buf, canonical_path.len)) { | 
281  | 0  |     strbuf_release(&canonical_path);  | 
282  |  |     /*  | 
283  |  |      * NEEDSWORK: Our caller already tried an exact match  | 
284  |  |      * and failed to find one.  They called us to do an  | 
285  |  |      * ICASE match, so we should never get an exact match,  | 
286  |  |      * so we could promote this to a BUG() here if we  | 
287  |  |      * wanted to.  It doesn't hurt anything to just return  | 
288  |  |      * 0 and go on because we should never get here.  Or we  | 
289  |  |      * could just get rid of the memcmp() and this "if"  | 
290  |  |      * clause completely.  | 
291  |  |      */  | 
292  | 0  |     BUG("handle_using_dir_name_hash_icase(%s) did not exact match", | 
293  | 0  |         name);  | 
294  | 0  |   }  | 
295  |  |  | 
296  | 0  |   trace_printf_key(&trace_fsmonitor,  | 
297  | 0  |        "fsmonitor_refresh_callback MAP: '%s' '%s'",  | 
298  | 0  |        name, canonical_path.buf);  | 
299  |  |  | 
300  |  |   /*  | 
301  |  |    * The dir-name-hash only tells us the corrected spelling of  | 
302  |  |    * the prefix.  We have to use this canonical path to do a  | 
303  |  |    * lookup in the cache-entry array so that we repeat the  | 
304  |  |    * original search using the case-corrected spelling.  | 
305  |  |    */  | 
306  | 0  |   strbuf_addch(&canonical_path, '/');  | 
307  | 0  |   pos = index_name_pos(istate, canonical_path.buf,  | 
308  | 0  |            canonical_path.len);  | 
309  | 0  |   nr_in_cone = handle_path_with_trailing_slash(  | 
310  | 0  |     istate, canonical_path.buf, pos);  | 
311  | 0  |   strbuf_release(&canonical_path);  | 
312  | 0  |   return nr_in_cone;  | 
313  | 0  | }  | 
314  |  |  | 
315  |  | /*  | 
316  |  |  * The daemon sent an observed pathname without a trailing slash.  | 
317  |  |  * (This is the normal case.)  We do not know if it is a tracked or  | 
318  |  |  * untracked file, a sparse-directory, or a populated directory (on a  | 
319  |  |  * platform such as Windows where FSEvents are not qualified).  | 
320  |  |  *  | 
321  |  |  * The pathname contains the observed case reported by the FS. We  | 
322  |  |  * do not know it is case-correct or -incorrect.  | 
323  |  |  *  | 
324  |  |  * Assume it is case-correct and try an exact match.  | 
325  |  |  *  | 
326  |  |  * Return the number of cache-entries that we invalidated.  | 
327  |  |  */  | 
328  |  | static size_t handle_path_without_trailing_slash(  | 
329  |  |   struct index_state *istate, const char *name, int pos)  | 
330  | 0  | { | 
331  |  |   /*  | 
332  |  |    * Mark the untracked cache dirty for this path (regardless of  | 
333  |  |    * whether or not we find an exact match for it in the index).  | 
334  |  |    * Since the path is unqualified (no trailing slash hint in the  | 
335  |  |    * FSEvent), it may refer to a file or directory. So we should  | 
336  |  |    * not assume one or the other and should always let the untracked  | 
337  |  |    * cache decide what needs to invalidated.  | 
338  |  |    */  | 
339  | 0  |   untracked_cache_invalidate_trimmed_path(istate, name, 0);  | 
340  |  | 
  | 
341  | 0  |   if (pos >= 0) { | 
342  |  |     /*  | 
343  |  |      * An exact match on a tracked file. We assume that we  | 
344  |  |      * do not need to scan forward for a sparse-directory  | 
345  |  |      * cache-entry with the same pathname, nor for a cone  | 
346  |  |      * at that directory. (That is, assume no D/F conflicts.)  | 
347  |  |      */  | 
348  | 0  |     invalidate_ce_fsm(istate->cache[pos]);  | 
349  | 0  |     return 1;  | 
350  | 0  |   } else { | 
351  | 0  |     size_t nr_in_cone;  | 
352  | 0  |     struct strbuf work_path = STRBUF_INIT;  | 
353  |  |  | 
354  |  |     /*  | 
355  |  |      * The negative "pos" gives us the suggested insertion  | 
356  |  |      * point for the pathname (without the trailing slash).  | 
357  |  |      * We need to see if there is a directory with that  | 
358  |  |      * prefix, but there can be lots of pathnames between  | 
359  |  |      * "foo" and "foo/" like "foo-" or "foo-bar", so we  | 
360  |  |      * don't want to do our own scan.  | 
361  |  |      */  | 
362  | 0  |     strbuf_add(&work_path, name, strlen(name));  | 
363  | 0  |     strbuf_addch(&work_path, '/');  | 
364  | 0  |     pos = index_name_pos(istate, work_path.buf, work_path.len);  | 
365  | 0  |     nr_in_cone = handle_path_with_trailing_slash(  | 
366  | 0  |       istate, work_path.buf, pos);  | 
367  | 0  |     strbuf_release(&work_path);  | 
368  | 0  |     return nr_in_cone;  | 
369  | 0  |   }  | 
370  | 0  | }  | 
371  |  |  | 
372  |  | /*  | 
373  |  |  * The daemon can decorate directory events, such as a move or rename,  | 
374  |  |  * by adding a trailing slash to the observed name.  Use this to  | 
375  |  |  * explicitly invalidate the entire cone under that directory.  | 
376  |  |  *  | 
377  |  |  * The daemon can only reliably do that if the OS FSEvent contains  | 
378  |  |  * sufficient information in the event.  | 
379  |  |  *  | 
380  |  |  * macOS FSEvents have enough information.  | 
381  |  |  *  | 
382  |  |  * Other platforms may or may not be able to do it (and it might  | 
383  |  |  * depend on the type of event (for example, a daemon could lstat() an  | 
384  |  |  * observed pathname after a rename, but not after a delete)).  | 
385  |  |  *  | 
386  |  |  * If we find an exact match in the index for a path with a trailing  | 
387  |  |  * slash, it means that we matched a sparse-index directory in a  | 
388  |  |  * cone-mode sparse-checkout (since that's the only time we have  | 
389  |  |  * directories in the index).  We should never see this in practice  | 
390  |  |  * (because sparse directories should not be present and therefore  | 
391  |  |  * not generating FS events).  Either way, we can treat them in the  | 
392  |  |  * same way and just invalidate the cache-entry and the untracked  | 
393  |  |  * cache (and in this case, the forward cache-entry scan won't find  | 
394  |  |  * anything and it doesn't hurt to let it run).  | 
395  |  |  *  | 
396  |  |  * Return the number of cache-entries that we invalidated.  We will  | 
397  |  |  * use this later to determine if we need to attempt a second  | 
398  |  |  * case-insensitive search on case-insensitive file systems.  That is,  | 
399  |  |  * if the search using the observed-case in the FSEvent yields any  | 
400  |  |  * results, we assume the prefix is case-correct.  If there are no  | 
401  |  |  * matches, we still don't know if the observed path is simply  | 
402  |  |  * untracked or case-incorrect.  | 
403  |  |  */  | 
404  |  | static size_t handle_path_with_trailing_slash(  | 
405  |  |   struct index_state *istate, const char *name, int pos)  | 
406  | 0  | { | 
407  | 0  |   int i;  | 
408  | 0  |   size_t nr_in_cone = 0;  | 
409  |  |  | 
410  |  |   /*  | 
411  |  |    * Mark the untracked cache dirty for this directory path  | 
412  |  |    * (regardless of whether or not we find an exact match for it  | 
413  |  |    * in the index or find it to be proper prefix of one or more  | 
414  |  |    * files in the index), since the FSEvent is hinting that  | 
415  |  |    * there may be changes on or within the directory.  | 
416  |  |    */  | 
417  | 0  |   untracked_cache_invalidate_trimmed_path(istate, name, 0);  | 
418  |  | 
  | 
419  | 0  |   if (pos < 0)  | 
420  | 0  |     pos = -pos - 1;  | 
421  |  |  | 
422  |  |   /* Mark all entries for the folder invalid */  | 
423  | 0  |   for (i = pos; i < istate->cache_nr; i++) { | 
424  | 0  |     if (!starts_with(istate->cache[i]->name, name))  | 
425  | 0  |       break;  | 
426  | 0  |     invalidate_ce_fsm(istate->cache[i]);  | 
427  | 0  |     nr_in_cone++;  | 
428  | 0  |   }  | 
429  |  | 
  | 
430  | 0  |   return nr_in_cone;  | 
431  | 0  | }  | 
432  |  |  | 
433  |  | static void fsmonitor_refresh_callback(struct index_state *istate, char *name)  | 
434  | 0  | { | 
435  | 0  |   int len = strlen(name);  | 
436  | 0  |   int pos = index_name_pos(istate, name, len);  | 
437  | 0  |   size_t nr_in_cone;  | 
438  |  | 
  | 
439  | 0  |   trace_printf_key(&trace_fsmonitor,  | 
440  | 0  |        "fsmonitor_refresh_callback '%s' (pos %d)",  | 
441  | 0  |        name, pos);  | 
442  |  | 
  | 
443  | 0  |   if (name[len - 1] == '/')  | 
444  | 0  |     nr_in_cone = handle_path_with_trailing_slash(istate, name, pos);  | 
445  | 0  |   else  | 
446  | 0  |     nr_in_cone = handle_path_without_trailing_slash(istate, name, pos);  | 
447  |  |  | 
448  |  |   /*  | 
449  |  |    * If we did not find an exact match for this pathname or any  | 
450  |  |    * cache-entries with this directory prefix and we're on a  | 
451  |  |    * case-insensitive file system, try again using the name-hash  | 
452  |  |    * and dir-name-hash.  | 
453  |  |    */  | 
454  | 0  |   if (!nr_in_cone && ignore_case) { | 
455  | 0  |     nr_in_cone = handle_using_name_hash_icase(istate, name);  | 
456  | 0  |     if (!nr_in_cone)  | 
457  | 0  |       nr_in_cone = handle_using_dir_name_hash_icase(  | 
458  | 0  |         istate, name);  | 
459  | 0  |   }  | 
460  |  | 
  | 
461  | 0  |   if (nr_in_cone)  | 
462  | 0  |     trace_printf_key(&trace_fsmonitor,  | 
463  | 0  |          "fsmonitor_refresh_callback CNT: %d",  | 
464  | 0  |          (int)nr_in_cone);  | 
465  | 0  | }  | 
466  |  |  | 
467  |  | /*  | 
468  |  |  * The number of pathnames that we need to receive from FSMonitor  | 
469  |  |  * before we force the index to be updated.  | 
470  |  |  *  | 
471  |  |  * Note that any pathname within the set of received paths MAY cause  | 
472  |  |  * cache-entry or istate flag bits to be updated and thus cause the  | 
473  |  |  * index to be updated on disk.  | 
474  |  |  *  | 
475  |  |  * However, the response may contain many paths (such as ignored  | 
476  |  |  * paths) that will not update any flag bits.  And thus not force the  | 
477  |  |  * index to be updated.  (This is fine and normal.)  It also means  | 
478  |  |  * that the token will not be updated in the FSMonitor index  | 
479  |  |  * extension.  So the next Git command will find the same token in the  | 
480  |  |  * index, make the same token-relative request, and receive the same  | 
481  |  |  * response (plus any newly changed paths).  If this response is large  | 
482  |  |  * (and continues to grow), performance could be impacted.  | 
483  |  |  *  | 
484  |  |  * For example, if the user runs a build and it writes 100K object  | 
485  |  |  * files but doesn't modify any source files, the index would not need  | 
486  |  |  * to be updated.  The FSMonitor response (after the build and  | 
487  |  |  * relative to a pre-build token) might be 5MB.  Each subsequent Git  | 
488  |  |  * command will receive that same 100K/5MB response until something  | 
489  |  |  * causes the index to be updated.  And `refresh_fsmonitor()` will  | 
490  |  |  * have to iterate over those 100K paths each time.  | 
491  |  |  *  | 
492  |  |  * Performance could be improved if we optionally force update the  | 
493  |  |  * index after a very large response and get an updated token into  | 
494  |  |  * the FSMonitor index extension.  This should allow subsequent  | 
495  |  |  * commands to get smaller and more current responses.  | 
496  |  |  *  | 
497  |  |  * The value chosen here does not need to be precise.  The index  | 
498  |  |  * will be updated automatically the first time the user touches  | 
499  |  |  * a tracked file and causes a command like `git status` to  | 
500  |  |  * update an mtime to be updated and/or set a flag bit.  | 
501  |  |  */  | 
502  |  | static int fsmonitor_force_update_threshold = 100;  | 
503  |  |  | 
504  |  | void refresh_fsmonitor(struct index_state *istate)  | 
505  | 0  | { | 
506  | 0  |   static int warn_once = 0;  | 
507  | 0  |   struct strbuf query_result = STRBUF_INIT;  | 
508  | 0  |   int query_success = 0, hook_version = -1;  | 
509  | 0  |   size_t bol = 0; /* beginning of line */  | 
510  | 0  |   uint64_t last_update;  | 
511  | 0  |   struct strbuf last_update_token = STRBUF_INIT;  | 
512  | 0  |   char *buf;  | 
513  | 0  |   unsigned int i;  | 
514  | 0  |   int is_trivial = 0;  | 
515  | 0  |   struct repository *r = istate->repo;  | 
516  | 0  |   enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);  | 
517  | 0  |   enum fsmonitor_reason reason = fsm_settings__get_reason(r);  | 
518  |  | 
  | 
519  | 0  |   if (!warn_once && reason > FSMONITOR_REASON_OK) { | 
520  | 0  |     char *msg = fsm_settings__get_incompatible_msg(r, reason);  | 
521  | 0  |     warn_once = 1;  | 
522  | 0  |     warning("%s", msg); | 
523  | 0  |     free(msg);  | 
524  | 0  |   }  | 
525  |  | 
  | 
526  | 0  |   if (fsm_mode <= FSMONITOR_MODE_DISABLED ||  | 
527  | 0  |       istate->fsmonitor_has_run_once)  | 
528  | 0  |     return;  | 
529  |  |  | 
530  | 0  |   istate->fsmonitor_has_run_once = 1;  | 
531  |  | 
  | 
532  | 0  |   trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");  | 
533  |  | 
  | 
534  | 0  |   if (fsm_mode == FSMONITOR_MODE_IPC) { | 
535  | 0  |     query_success = !fsmonitor_ipc__send_query(  | 
536  | 0  |       istate->fsmonitor_last_update ?  | 
537  | 0  |       istate->fsmonitor_last_update : "builtin:fake",  | 
538  | 0  |       &query_result);  | 
539  | 0  |     if (query_success) { | 
540  |  |       /*  | 
541  |  |        * The response contains a series of nul terminated  | 
542  |  |        * strings.  The first is the new token.  | 
543  |  |        *  | 
544  |  |        * Use `char *buf` as an interlude to trick the CI  | 
545  |  |        * static analysis to let us use `strbuf_addstr()`  | 
546  |  |        * here (and only copy the token) rather than  | 
547  |  |        * `strbuf_addbuf()`.  | 
548  |  |        */  | 
549  | 0  |       buf = query_result.buf;  | 
550  | 0  |       strbuf_addstr(&last_update_token, buf);  | 
551  | 0  |       bol = last_update_token.len + 1;  | 
552  | 0  |       is_trivial = query_result.buf[bol] == '/';  | 
553  | 0  |       if (is_trivial)  | 
554  | 0  |         trace2_data_intmax("fsm_client", NULL, | 
555  | 0  |                "query/trivial-response", 1);  | 
556  | 0  |     } else { | 
557  |  |       /*  | 
558  |  |        * The builtin daemon is not available on this  | 
559  |  |        * platform -OR- we failed to get a response.  | 
560  |  |        *  | 
561  |  |        * Generate a fake token (rather than a V1  | 
562  |  |        * timestamp) for the index extension.  (If  | 
563  |  |        * they switch back to the hook API, we don't  | 
564  |  |        * want ambiguous state.)  | 
565  |  |        */  | 
566  | 0  |       strbuf_addstr(&last_update_token, "builtin:fake");  | 
567  | 0  |     }  | 
568  |  | 
  | 
569  | 0  |     goto apply_results;  | 
570  | 0  |   }  | 
571  |  |  | 
572  | 0  |   assert(fsm_mode == FSMONITOR_MODE_HOOK);  | 
573  |  |  | 
574  | 0  |   hook_version = fsmonitor_hook_version();  | 
575  |  |  | 
576  |  |   /*  | 
577  |  |    * This could be racy so save the date/time now and query_fsmonitor_hook  | 
578  |  |    * should be inclusive to ensure we don't miss potential changes.  | 
579  |  |    */  | 
580  | 0  |   last_update = getnanotime();  | 
581  | 0  |   if (hook_version == HOOK_INTERFACE_VERSION1)  | 
582  | 0  |     strbuf_addf(&last_update_token, "%"PRIu64"", last_update);  | 
583  |  |  | 
584  |  |   /*  | 
585  |  |    * If we have a last update token, call query_fsmonitor_hook for the set of  | 
586  |  |    * changes since that token, else assume everything is possibly dirty  | 
587  |  |    * and check it all.  | 
588  |  |    */  | 
589  | 0  |   if (istate->fsmonitor_last_update) { | 
590  | 0  |     if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) { | 
591  | 0  |       query_success = !query_fsmonitor_hook(  | 
592  | 0  |         r, HOOK_INTERFACE_VERSION2,  | 
593  | 0  |         istate->fsmonitor_last_update, &query_result);  | 
594  |  | 
  | 
595  | 0  |       if (query_success) { | 
596  | 0  |         if (hook_version < 0)  | 
597  | 0  |           hook_version = HOOK_INTERFACE_VERSION2;  | 
598  |  |  | 
599  |  |         /*  | 
600  |  |          * First entry will be the last update token  | 
601  |  |          * Need to use a char * variable because static  | 
602  |  |          * analysis was suggesting to use strbuf_addbuf  | 
603  |  |          * but we don't want to copy the entire strbuf  | 
604  |  |          * only the chars up to the first NUL  | 
605  |  |          */  | 
606  | 0  |         buf = query_result.buf;  | 
607  | 0  |         strbuf_addstr(&last_update_token, buf);  | 
608  | 0  |         if (!last_update_token.len) { | 
609  | 0  |           warning("Empty last update token."); | 
610  | 0  |           query_success = 0;  | 
611  | 0  |         } else { | 
612  | 0  |           bol = last_update_token.len + 1;  | 
613  | 0  |           is_trivial = query_result.buf[bol] == '/';  | 
614  | 0  |         }  | 
615  | 0  |       } else if (hook_version < 0) { | 
616  | 0  |         hook_version = HOOK_INTERFACE_VERSION1;  | 
617  | 0  |         if (!last_update_token.len)  | 
618  | 0  |           strbuf_addf(&last_update_token, "%"PRIu64"", last_update);  | 
619  | 0  |       }  | 
620  | 0  |     }  | 
621  |  | 
  | 
622  | 0  |     if (hook_version == HOOK_INTERFACE_VERSION1) { | 
623  | 0  |       query_success = !query_fsmonitor_hook(  | 
624  | 0  |         r, HOOK_INTERFACE_VERSION1,  | 
625  | 0  |         istate->fsmonitor_last_update, &query_result);  | 
626  | 0  |       if (query_success)  | 
627  | 0  |         is_trivial = query_result.buf[0] == '/';  | 
628  | 0  |     }  | 
629  |  | 
  | 
630  | 0  |     if (is_trivial)  | 
631  | 0  |       trace2_data_intmax("fsm_hook", NULL, | 
632  | 0  |              "query/trivial-response", 1);  | 
633  |  | 
  | 
634  | 0  |     trace_performance_since(last_update, "fsmonitor process '%s'",  | 
635  | 0  |           fsm_settings__get_hook_path(r));  | 
636  | 0  |     trace_printf_key(&trace_fsmonitor,  | 
637  | 0  |          "fsmonitor process '%s' returned %s",  | 
638  | 0  |          fsm_settings__get_hook_path(r),  | 
639  | 0  |          query_success ? "success" : "failure");  | 
640  | 0  |   }  | 
641  |  | 
  | 
642  | 0  | apply_results:  | 
643  |  |   /*  | 
644  |  |    * The response from FSMonitor (excluding the header token) is  | 
645  |  |    * either:  | 
646  |  |    *  | 
647  |  |    * [a] a (possibly empty) list of NUL delimited relative  | 
648  |  |    *     pathnames of changed paths.  This list can contain  | 
649  |  |    *     files and directories.  Directories have a trailing  | 
650  |  |    *     slash.  | 
651  |  |    *  | 
652  |  |    * [b] a single '/' to indicate the provider had no  | 
653  |  |    *     information and that we should consider everything  | 
654  |  |    *     invalid.  We call this a trivial response.  | 
655  |  |    */  | 
656  | 0  |   trace2_region_enter("fsmonitor", "apply_results", istate->repo); | 
657  |  | 
  | 
658  | 0  |   if (query_success && !is_trivial) { | 
659  |  |     /*  | 
660  |  |      * Mark all pathnames returned by the monitor as dirty.  | 
661  |  |      *  | 
662  |  |      * This updates both the cache-entries and the untracked-cache.  | 
663  |  |      */  | 
664  | 0  |     int count = 0;  | 
665  |  | 
  | 
666  | 0  |     buf = query_result.buf;  | 
667  | 0  |     for (i = bol; i < query_result.len; i++) { | 
668  | 0  |       if (buf[i] != '\0')  | 
669  | 0  |         continue;  | 
670  | 0  |       fsmonitor_refresh_callback(istate, buf + bol);  | 
671  | 0  |       bol = i + 1;  | 
672  | 0  |       count++;  | 
673  | 0  |     }  | 
674  | 0  |     if (bol < query_result.len) { | 
675  | 0  |       fsmonitor_refresh_callback(istate, buf + bol);  | 
676  | 0  |       count++;  | 
677  | 0  |     }  | 
678  |  |  | 
679  |  |     /* Now mark the untracked cache for fsmonitor usage */  | 
680  | 0  |     if (istate->untracked)  | 
681  | 0  |       istate->untracked->use_fsmonitor = 1;  | 
682  |  | 
  | 
683  | 0  |     if (count > fsmonitor_force_update_threshold)  | 
684  | 0  |       istate->cache_changed |= FSMONITOR_CHANGED;  | 
685  |  | 
  | 
686  | 0  |     trace2_data_intmax("fsmonitor", istate->repo, "apply_count", | 
687  | 0  |            count);  | 
688  |  | 
  | 
689  | 0  |   } else { | 
690  |  |     /*  | 
691  |  |      * We failed to get a response or received a trivial response,  | 
692  |  |      * so invalidate everything.  | 
693  |  |      *  | 
694  |  |      * We only want to run the post index changed hook if  | 
695  |  |      * we've actually changed entries, so keep track if we  | 
696  |  |      * actually changed entries or not.  | 
697  |  |      */  | 
698  | 0  |     int is_cache_changed = 0;  | 
699  |  | 
  | 
700  | 0  |     for (i = 0; i < istate->cache_nr; i++) { | 
701  | 0  |       if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) { | 
702  | 0  |         is_cache_changed = 1;  | 
703  | 0  |         istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;  | 
704  | 0  |       }  | 
705  | 0  |     }  | 
706  |  |  | 
707  |  |     /*  | 
708  |  |      * If we're going to check every file, ensure we save  | 
709  |  |      * the results.  | 
710  |  |      */  | 
711  | 0  |     if (is_cache_changed)  | 
712  | 0  |       istate->cache_changed |= FSMONITOR_CHANGED;  | 
713  |  | 
  | 
714  | 0  |     if (istate->untracked)  | 
715  | 0  |       istate->untracked->use_fsmonitor = 0;  | 
716  | 0  |   }  | 
717  | 0  |   trace2_region_leave("fsmonitor", "apply_results", istate->repo); | 
718  |  | 
  | 
719  | 0  |   strbuf_release(&query_result);  | 
720  |  |  | 
721  |  |   /* Now that we've updated istate, save the last_update_token */  | 
722  | 0  |   FREE_AND_NULL(istate->fsmonitor_last_update);  | 
723  | 0  |   istate->fsmonitor_last_update = strbuf_detach(&last_update_token, NULL);  | 
724  | 0  | }  | 
725  |  |  | 
726  |  | /*  | 
727  |  |  * The caller wants to turn on FSMonitor.  And when the caller writes  | 
728  |  |  * the index to disk, a FSMonitor extension should be included.  This  | 
729  |  |  * requires that `istate->fsmonitor_last_update` not be NULL.  But we  | 
730  |  |  * have not actually talked to a FSMonitor process yet, so we don't  | 
731  |  |  * have an initial value for this field.  | 
732  |  |  *  | 
733  |  |  * For a protocol V1 FSMonitor process, this field is a formatted  | 
734  |  |  * "nanoseconds since epoch" field.  However, for a protocol V2  | 
735  |  |  * FSMonitor process, this field is an opaque token.  | 
736  |  |  *  | 
737  |  |  * Historically, `add_fsmonitor()` has initialized this field to the  | 
738  |  |  * current time for protocol V1 processes.  There are lots of race  | 
739  |  |  * conditions here, but that code has shipped...  | 
740  |  |  *  | 
741  |  |  * The only true solution is to use a V2 FSMonitor and get a current  | 
742  |  |  * or default token value (that it understands), but we cannot do that  | 
743  |  |  * until we have actually talked to an instance of the FSMonitor process  | 
744  |  |  * (but the protocol requires that we send a token first...).  | 
745  |  |  *  | 
746  |  |  * For simplicity, just initialize like we have a V1 process and require  | 
747  |  |  * that V2 processes adapt.  | 
748  |  |  */  | 
749  |  | static void initialize_fsmonitor_last_update(struct index_state *istate)  | 
750  | 0  | { | 
751  | 0  |   struct strbuf last_update = STRBUF_INIT;  | 
752  |  | 
  | 
753  | 0  |   strbuf_addf(&last_update, "%"PRIu64"", getnanotime());  | 
754  | 0  |   istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);  | 
755  | 0  | }  | 
756  |  |  | 
757  |  | void add_fsmonitor(struct index_state *istate)  | 
758  | 0  | { | 
759  | 0  |   unsigned int i;  | 
760  |  | 
  | 
761  | 0  |   if (!istate->fsmonitor_last_update) { | 
762  | 0  |     trace_printf_key(&trace_fsmonitor, "add fsmonitor");  | 
763  | 0  |     istate->cache_changed |= FSMONITOR_CHANGED;  | 
764  | 0  |     initialize_fsmonitor_last_update(istate);  | 
765  |  |  | 
766  |  |     /* reset the fsmonitor state */  | 
767  | 0  |     for (i = 0; i < istate->cache_nr; i++)  | 
768  | 0  |       istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;  | 
769  |  |  | 
770  |  |     /* reset the untracked cache */  | 
771  | 0  |     if (istate->untracked) { | 
772  | 0  |       add_untracked_cache(istate);  | 
773  | 0  |       istate->untracked->use_fsmonitor = 1;  | 
774  | 0  |     }  | 
775  |  |  | 
776  |  |     /* Update the fsmonitor state */  | 
777  | 0  |     refresh_fsmonitor(istate);  | 
778  | 0  |   }  | 
779  | 0  | }  | 
780  |  |  | 
781  |  | void remove_fsmonitor(struct index_state *istate)  | 
782  | 0  | { | 
783  | 0  |   if (istate->fsmonitor_last_update) { | 
784  | 0  |     trace_printf_key(&trace_fsmonitor, "remove fsmonitor");  | 
785  | 0  |     istate->cache_changed |= FSMONITOR_CHANGED;  | 
786  | 0  |     FREE_AND_NULL(istate->fsmonitor_last_update);  | 
787  | 0  |   }  | 
788  | 0  | }  | 
789  |  |  | 
790  |  | void tweak_fsmonitor(struct index_state *istate)  | 
791  | 0  | { | 
792  | 0  |   unsigned int i;  | 
793  | 0  |   int fsmonitor_enabled = (fsm_settings__get_mode(istate->repo)  | 
794  | 0  |          > FSMONITOR_MODE_DISABLED);  | 
795  |  | 
  | 
796  | 0  |   if (istate->fsmonitor_dirty) { | 
797  | 0  |     if (fsmonitor_enabled) { | 
798  |  |       /* Mark all entries valid */  | 
799  | 0  |       for (i = 0; i < istate->cache_nr; i++) { | 
800  | 0  |         if (S_ISGITLINK(istate->cache[i]->ce_mode))  | 
801  | 0  |           continue;  | 
802  | 0  |         istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;  | 
803  | 0  |       }  | 
804  |  |  | 
805  |  |       /* Mark all previously saved entries as dirty */  | 
806  | 0  |       assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);  | 
807  | 0  |       ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);  | 
808  |  | 
  | 
809  | 0  |       refresh_fsmonitor(istate);  | 
810  | 0  |     }  | 
811  |  | 
  | 
812  | 0  |     ewah_free(istate->fsmonitor_dirty);  | 
813  | 0  |     istate->fsmonitor_dirty = NULL;  | 
814  | 0  |   }  | 
815  |  | 
  | 
816  | 0  |   if (fsmonitor_enabled)  | 
817  | 0  |     add_fsmonitor(istate);  | 
818  | 0  |   else  | 
819  | 0  |     remove_fsmonitor(istate);  | 
820  | 0  | }  |