If GIT_TEST_WATCHED is set to a non-zero value, Git still uses file watcher if configured. But it does lstat() anyway and notifies the user if a file is changed but the file watcher said otherwise. Note that there is a race condition. Changed paths are retrieved at time X, then refresh and validation at time Y. Even if X and Y are very close, an update can happen between X and Y, causing a false report. If GIT_TEST_WATCHED is set greater than 1, git will abort instead of just warn and move on. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- Documentation/git-file-watcher.txt | 8 ++++++++ cache.h | 5 ++++- read-cache.c | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Documentation/git-file-watcher.txt b/Documentation/git-file-watcher.txt index d694fea..dd09e30 100644 --- a/Documentation/git-file-watcher.txt +++ b/Documentation/git-file-watcher.txt @@ -25,6 +25,14 @@ OPTIONS --detach:: Run in background. +TROUBLESHOOTING +--------------- +Setting environment variable `GIT_TEST_WATCHED` to a non-zero number +makes Git communicate with the file watcher, but do lstat anyway to +verify that the file watcher results. Setting to 1 prints warning when +file watcher fails to monitor files correctly. Setting to 2 aborts Git +when it happens. + BUGS ---- On Linux, file watcher may fail to detect changes if you move the work diff --git a/cache.h b/cache.h index c229bf9..806c886 100644 --- a/cache.h +++ b/cache.h @@ -224,7 +224,10 @@ static inline unsigned create_ce_flags(unsigned stage) #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE) static inline int ce_valid(const struct cache_entry *ce) { - return ce->ce_flags & CE_VALID; + extern int test_watched; + if (!test_watched) + return ce->ce_flags & CE_VALID; + return (ce->ce_flags & CE_VALID) && !(ce->ce_flags & CE_WATCHED); } #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) diff --git a/read-cache.c b/read-cache.c index 95c9ccb..d5f084a 100644 --- a/read-cache.c +++ b/read-cache.c @@ -37,6 +37,7 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int reall #define CACHE_EXT_WATCH 0x57415443 /* "WATC" */ struct index_state the_index; +int test_watched; static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce) { @@ -1117,6 +1118,16 @@ static void show_file(const char * fmt, const char * name, int in_porcelain, printf(fmt, name); } +static void report_bad_watcher(struct index_state *istate, + struct cache_entry *ce) +{ + if (test_watched > 1) + die("%s is updated but file-watcher said no", + ce->name); + warning("%s is updated but file-watcher said no", + ce->name); +} + int refresh_index(struct index_state *istate, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg) @@ -1188,6 +1199,9 @@ int refresh_index(struct index_state *istate, unsigned int flags, ce->ce_flags &= ~CE_VALID; istate->cache_changed = 1; } + if (test_watched && + (ce->ce_flags & CE_WATCHED) && (ce->ce_flags & CE_VALID)) + report_bad_watcher(istate, ce); if (quiet) continue; @@ -1460,6 +1474,9 @@ int read_index_from(struct index_state *istate, const char *path) if (istate->initialized) return istate->cache_nr; + if (getenv("GIT_TEST_WATCHED")) + test_watched = atoi(getenv("GIT_TEST_WATCHED")); + istate->timestamp.sec = 0; istate->timestamp.nsec = 0; fd = open(path, O_RDONLY); -- 1.8.5.2.240.g8478abd -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html