From daeb515a28d508b16babdd906168946172168c31 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:48 +0000 Subject: [PATCH 01/16] t/test-lib: avoid using git on LHS of pipe fixup! help: include fsmonitor--daemon feature flag in version info Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/test-lib.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index 46cd596e7f5af5..5d819c1bc11c34 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1803,5 +1803,6 @@ GIT_TEST_MAINT_SCHEDULER="none:exit 1" # Does this platform support `git fsmonitor--daemon` # test_lazy_prereq FSMONITOR_DAEMON ' - git version --build-options | grep "feature:" | grep "fsmonitor--daemon" + git version --build-options >output && + grep "feature: fsmonitor--daemon" output ' From a0ec6d36dbc31038c1551fdcb2d440abe1a100ea Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:49 +0000 Subject: [PATCH 02/16] update-index: convert advise() messages back to warning() fixup! update-index: convert fsmonitor warnings to advise Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- builtin/update-index.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builtin/update-index.c b/builtin/update-index.c index d335f1ac72ab54..75d646377ccdcb 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -1238,18 +1238,18 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) if (fsmonitor > 0) { enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r); if (fsm_mode == FSMONITOR_MODE_DISABLED) { - advise(_("core.fsmonitor is unset; " - "set it if you really want to " - "enable fsmonitor")); + warning(_("core.fsmonitor is unset; " + "set it if you really want to " + "enable fsmonitor")); } add_fsmonitor(&the_index); report(_("fsmonitor enabled")); } else if (!fsmonitor) { enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r); if (fsm_mode > FSMONITOR_MODE_DISABLED) - advise(_("core.fsmonitor is set; " - "remove it if you really want to " - "disable fsmonitor")); + warning(_("core.fsmonitor is set; " + "remove it if you really want to " + "disable fsmonitor")); remove_fsmonitor(&the_index); report(_("fsmonitor disabled")); } From 25db37afabb87f5838c500d15afcb263cd34f6f3 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:50 +0000 Subject: [PATCH 03/16] compat/fsmonitor/fsm-listen-darwin: split out GCC-specific declarations fixup! compat/fsmonitor/fsm-listen-darwin: add MacOS header files \ for FSEvent Split out GCC-specific MacOS declarations into separate file from the clang-specific header file includes to reduce visual noise. Eliminate unnecessary includes when using clang. Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- compat/fsmonitor/fsm-darwin-gcc.h | 92 ++++++++++++++++++++++++++++ compat/fsmonitor/fsm-listen-darwin.c | 91 +-------------------------- 2 files changed, 93 insertions(+), 90 deletions(-) create mode 100644 compat/fsmonitor/fsm-darwin-gcc.h diff --git a/compat/fsmonitor/fsm-darwin-gcc.h b/compat/fsmonitor/fsm-darwin-gcc.h new file mode 100644 index 00000000000000..1c75c3d48e7d7c --- /dev/null +++ b/compat/fsmonitor/fsm-darwin-gcc.h @@ -0,0 +1,92 @@ +#ifndef FSM_DARWIN_GCC_H +#define FSM_DARWIN_GCC_H + +#ifndef __clang__ +/* + * It is possible to #include CoreFoundation/CoreFoundation.h when compiling + * with clang, but not with GCC as of time of writing. + * + * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93082 for details. + */ +typedef unsigned int FSEventStreamCreateFlags; +#define kFSEventStreamEventFlagNone 0x00000000 +#define kFSEventStreamEventFlagMustScanSubDirs 0x00000001 +#define kFSEventStreamEventFlagUserDropped 0x00000002 +#define kFSEventStreamEventFlagKernelDropped 0x00000004 +#define kFSEventStreamEventFlagEventIdsWrapped 0x00000008 +#define kFSEventStreamEventFlagHistoryDone 0x00000010 +#define kFSEventStreamEventFlagRootChanged 0x00000020 +#define kFSEventStreamEventFlagMount 0x00000040 +#define kFSEventStreamEventFlagUnmount 0x00000080 +#define kFSEventStreamEventFlagItemCreated 0x00000100 +#define kFSEventStreamEventFlagItemRemoved 0x00000200 +#define kFSEventStreamEventFlagItemInodeMetaMod 0x00000400 +#define kFSEventStreamEventFlagItemRenamed 0x00000800 +#define kFSEventStreamEventFlagItemModified 0x00001000 +#define kFSEventStreamEventFlagItemFinderInfoMod 0x00002000 +#define kFSEventStreamEventFlagItemChangeOwner 0x00004000 +#define kFSEventStreamEventFlagItemXattrMod 0x00008000 +#define kFSEventStreamEventFlagItemIsFile 0x00010000 +#define kFSEventStreamEventFlagItemIsDir 0x00020000 +#define kFSEventStreamEventFlagItemIsSymlink 0x00040000 +#define kFSEventStreamEventFlagOwnEvent 0x00080000 +#define kFSEventStreamEventFlagItemIsHardlink 0x00100000 +#define kFSEventStreamEventFlagItemIsLastHardlink 0x00200000 +#define kFSEventStreamEventFlagItemCloned 0x00400000 + +typedef struct __FSEventStream *FSEventStreamRef; +typedef const FSEventStreamRef ConstFSEventStreamRef; + +typedef unsigned int CFStringEncoding; +#define kCFStringEncodingUTF8 0x08000100 + +typedef const struct __CFString *CFStringRef; +typedef const struct __CFArray *CFArrayRef; +typedef const struct __CFRunLoop *CFRunLoopRef; + +struct FSEventStreamContext { + long long version; + void *cb_data, *retain, *release, *copy_description; +}; + +typedef struct FSEventStreamContext FSEventStreamContext; +typedef unsigned int FSEventStreamEventFlags; +#define kFSEventStreamCreateFlagNoDefer 0x02 +#define kFSEventStreamCreateFlagWatchRoot 0x04 +#define kFSEventStreamCreateFlagFileEvents 0x10 + +typedef unsigned long long FSEventStreamEventId; +#define kFSEventStreamEventIdSinceNow 0xFFFFFFFFFFFFFFFFULL + +typedef void (*FSEventStreamCallback)(ConstFSEventStreamRef streamRef, + void *context, + __SIZE_TYPE__ num_of_events, + void *event_paths, + const FSEventStreamEventFlags event_flags[], + const FSEventStreamEventId event_ids[]); +typedef double CFTimeInterval; +FSEventStreamRef FSEventStreamCreate(void *allocator, + FSEventStreamCallback callback, + FSEventStreamContext *context, + CFArrayRef paths_to_watch, + FSEventStreamEventId since_when, + CFTimeInterval latency, + FSEventStreamCreateFlags flags); +CFStringRef CFStringCreateWithCString(void *allocator, const char *string, + CFStringEncoding encoding); +CFArrayRef CFArrayCreate(void *allocator, const void **items, long long count, + void *callbacks); +void CFRunLoopRun(void); +void CFRunLoopStop(CFRunLoopRef run_loop); +CFRunLoopRef CFRunLoopGetCurrent(void); +extern CFStringRef kCFRunLoopDefaultMode; +void FSEventStreamScheduleWithRunLoop(FSEventStreamRef stream, + CFRunLoopRef run_loop, + CFStringRef run_loop_mode); +unsigned char FSEventStreamStart(FSEventStreamRef stream); +void FSEventStreamStop(FSEventStreamRef stream); +void FSEventStreamInvalidate(FSEventStreamRef stream); +void FSEventStreamRelease(FSEventStreamRef stream); + +#endif /* !clang */ +#endif /* FSM_DARWIN_GCC_H */ diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c index 5c5de1ae702aa6..9a73fb607d5b2c 100644 --- a/compat/fsmonitor/fsm-listen-darwin.c +++ b/compat/fsmonitor/fsm-listen-darwin.c @@ -1,95 +1,6 @@ #ifndef __clang__ -/* - * It is possible to #include CoreFoundation/CoreFoundation.h when compiling - * with clang, but not with GCC as of time of writing. - * - * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93082 for details. - */ -typedef unsigned int FSEventStreamCreateFlags; -#define kFSEventStreamEventFlagNone 0x00000000 -#define kFSEventStreamEventFlagMustScanSubDirs 0x00000001 -#define kFSEventStreamEventFlagUserDropped 0x00000002 -#define kFSEventStreamEventFlagKernelDropped 0x00000004 -#define kFSEventStreamEventFlagEventIdsWrapped 0x00000008 -#define kFSEventStreamEventFlagHistoryDone 0x00000010 -#define kFSEventStreamEventFlagRootChanged 0x00000020 -#define kFSEventStreamEventFlagMount 0x00000040 -#define kFSEventStreamEventFlagUnmount 0x00000080 -#define kFSEventStreamEventFlagItemCreated 0x00000100 -#define kFSEventStreamEventFlagItemRemoved 0x00000200 -#define kFSEventStreamEventFlagItemInodeMetaMod 0x00000400 -#define kFSEventStreamEventFlagItemRenamed 0x00000800 -#define kFSEventStreamEventFlagItemModified 0x00001000 -#define kFSEventStreamEventFlagItemFinderInfoMod 0x00002000 -#define kFSEventStreamEventFlagItemChangeOwner 0x00004000 -#define kFSEventStreamEventFlagItemXattrMod 0x00008000 -#define kFSEventStreamEventFlagItemIsFile 0x00010000 -#define kFSEventStreamEventFlagItemIsDir 0x00020000 -#define kFSEventStreamEventFlagItemIsSymlink 0x00040000 -#define kFSEventStreamEventFlagOwnEvent 0x00080000 -#define kFSEventStreamEventFlagItemIsHardlink 0x00100000 -#define kFSEventStreamEventFlagItemIsLastHardlink 0x00200000 -#define kFSEventStreamEventFlagItemCloned 0x00400000 - -typedef struct __FSEventStream *FSEventStreamRef; -typedef const FSEventStreamRef ConstFSEventStreamRef; - -typedef unsigned int CFStringEncoding; -#define kCFStringEncodingUTF8 0x08000100 - -typedef const struct __CFString *CFStringRef; -typedef const struct __CFArray *CFArrayRef; -typedef const struct __CFRunLoop *CFRunLoopRef; - -struct FSEventStreamContext { - long long version; - void *cb_data, *retain, *release, *copy_description; -}; - -typedef struct FSEventStreamContext FSEventStreamContext; -typedef unsigned int FSEventStreamEventFlags; -#define kFSEventStreamCreateFlagNoDefer 0x02 -#define kFSEventStreamCreateFlagWatchRoot 0x04 -#define kFSEventStreamCreateFlagFileEvents 0x10 - -typedef unsigned long long FSEventStreamEventId; -#define kFSEventStreamEventIdSinceNow 0xFFFFFFFFFFFFFFFFULL - -typedef void (*FSEventStreamCallback)(ConstFSEventStreamRef streamRef, - void *context, - __SIZE_TYPE__ num_of_events, - void *event_paths, - const FSEventStreamEventFlags event_flags[], - const FSEventStreamEventId event_ids[]); -typedef double CFTimeInterval; -FSEventStreamRef FSEventStreamCreate(void *allocator, - FSEventStreamCallback callback, - FSEventStreamContext *context, - CFArrayRef paths_to_watch, - FSEventStreamEventId since_when, - CFTimeInterval latency, - FSEventStreamCreateFlags flags); -CFStringRef CFStringCreateWithCString(void *allocator, const char *string, - CFStringEncoding encoding); -CFArrayRef CFArrayCreate(void *allocator, const void **items, long long count, - void *callbacks); -void CFRunLoopRun(void); -void CFRunLoopStop(CFRunLoopRef run_loop); -CFRunLoopRef CFRunLoopGetCurrent(void); -extern CFStringRef kCFRunLoopDefaultMode; -void FSEventStreamScheduleWithRunLoop(FSEventStreamRef stream, - CFRunLoopRef run_loop, - CFStringRef run_loop_mode); -unsigned char FSEventStreamStart(FSEventStreamRef stream); -void FSEventStreamStop(FSEventStreamRef stream); -void FSEventStreamInvalidate(FSEventStreamRef stream); -void FSEventStreamRelease(FSEventStreamRef stream); +#include "fsm-darwin-gcc.h" #else -/* - * Let Apple's headers declare `isalnum()` first, before - * Git's headers override it via a constant - */ -#include #include #include #endif From af179026e854eca72d5c5f7e69960ffcb20ac65e Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:51 +0000 Subject: [PATCH 04/16] t/helper/fsmonitor-client: cleanup call to parse_options() fixup! t/helper/fsmonitor-client: create IPC client to talk to \ FSMonitor Daemon Elminate unnecessary code in cmd__fsmonitor_client() WRT parsing of options. Fix name of test-tool in usage. Don't localize die() message. Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/helper/test-fsmonitor-client.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/t/helper/test-fsmonitor-client.c b/t/helper/test-fsmonitor-client.c index f7a5b3a32fab86..d59a640f1f92ff 100644 --- a/t/helper/test-fsmonitor-client.c +++ b/t/helper/test-fsmonitor-client.c @@ -49,7 +49,7 @@ static int do_send_query(const char *token) ret = fsmonitor_ipc__send_query(token, &answer); if (ret < 0) - die(_("could not query fsmonitor--daemon")); + die("could not query fsmonitor--daemon"); write_in_full(1, answer.buf, answer.len); strbuf_release(&answer); @@ -85,8 +85,8 @@ int cmd__fsmonitor_client(int argc, const char **argv) const char *token = NULL; const char * const fsmonitor_client_usage[] = { - N_("test-helper fsmonitor-client query []"), - N_("test-helper fsmonitor-client flush"), + N_("test-tool fsmonitor-client query []"), + N_("test-tool fsmonitor-client flush"), NULL, }; @@ -96,17 +96,12 @@ int cmd__fsmonitor_client(int argc, const char **argv) OPT_END() }; - if (argc < 2) - usage_with_options(fsmonitor_client_usage, options); + argc = parse_options(argc, argv, NULL, options, fsmonitor_client_usage, 0); - if (argc == 2 && !strcmp(argv[1], "-h")) + if (argc != 1) usage_with_options(fsmonitor_client_usage, options); - subcmd = argv[1]; - argv--; - argc++; - - argc = parse_options(argc, argv, NULL, options, fsmonitor_client_usage, 0); + subcmd = argv[0]; setup_git_directory(); From b0b1d8635c3fe6c5ecb467c22876ff3fb044d854 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:52 +0000 Subject: [PATCH 05/16] fsmonitor--daemon: refactor cookie handling for readability fixup! fsmonitor--daemon: use a cookie file to sync with file system Use implicit definitions for FCIR_ enum values. Remove const from cookie->name. Reverse if then and else branches around open() to ease readability. Document that we don't care about errors from close() and unlink(). Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- builtin/fsmonitor--daemon.c | 53 +++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 97ca2a356e54f9..02a99ce98a2508 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -109,14 +109,14 @@ static int do_as_client__status(void) enum fsmonitor_cookie_item_result { FCIR_ERROR = -1, /* could not create cookie file ? */ - FCIR_INIT = 0, + FCIR_INIT, FCIR_SEEN, FCIR_ABORT, }; struct fsmonitor_cookie_item { struct hashmap_entry entry; - const char *name; + char *name; enum fsmonitor_cookie_item_result result; }; @@ -166,37 +166,44 @@ static enum fsmonitor_cookie_item_result with_lock__wait_for_cookie( * that the listener thread has seen it. */ fd = open(cookie_pathname.buf, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd >= 0) { - close(fd); - unlink(cookie_pathname.buf); - - /* - * Technically, this is an infinite wait (well, unless another - * thread sends us an abort). I'd like to change this to - * use `pthread_cond_timedwait()` and return an error/timeout - * and let the caller do the trivial response thing, but we - * don't have that routine in our thread-utils. - * - * After extensive beta testing I'm not really worried about - * this. Also note that the above open() and unlink() calls - * will cause at least two FS events on that path, so the odds - * of getting stuck are pretty slim. - */ - while (cookie->result == FCIR_INIT) - pthread_cond_wait(&state->cookies_cond, - &state->main_lock); - } else { + if (fd < 0) { error_errno(_("could not create fsmonitor cookie '%s'"), cookie->name); cookie->result = FCIR_ERROR; + goto done; } + /* + * Technically, close() and unlink() can fail, but we don't + * care here. We only created the file to trigger a watch + * event from the FS to know that when we're up to date. + */ + close(fd); + unlink(cookie_pathname.buf); + + /* + * Technically, this is an infinite wait (well, unless another + * thread sends us an abort). I'd like to change this to + * use `pthread_cond_timedwait()` and return an error/timeout + * and let the caller do the trivial response thing, but we + * don't have that routine in our thread-utils. + * + * After extensive beta testing I'm not really worried about + * this. Also note that the above open() and unlink() calls + * will cause at least two FS events on that path, so the odds + * of getting stuck are pretty slim. + */ + while (cookie->result == FCIR_INIT) + pthread_cond_wait(&state->cookies_cond, + &state->main_lock); + +done: hashmap_remove(&state->cookies, &cookie->entry, NULL); result = cookie->result; - free((char*)cookie->name); + free(cookie->name); free(cookie); strbuf_release(&cookie_pathname); From ff5df55b8f116e6c537655144be90dc0d88d85b1 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:53 +0000 Subject: [PATCH 06/16] t/perf/p7519: use grep rather than egrep in test fixup! t/perf/p7519: speed up test on Windows Use grep rather than egrep Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/perf/p7519-fsmonitor.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/perf/p7519-fsmonitor.sh b/t/perf/p7519-fsmonitor.sh index a1c552129cc29b..5f97edf6a113b5 100755 --- a/t/perf/p7519-fsmonitor.sh +++ b/t/perf/p7519-fsmonitor.sh @@ -218,7 +218,7 @@ test_fsmonitor_suite () { git ls-files | \ head -100000 | \ grep -v \" | \ - egrep -v " ." | \ + grep -v " ." | \ xargs test-tool chmtime -300 && git status ' From 0b63104d8b8a6e3489a0e301a8717db23cf4cdd0 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:54 +0000 Subject: [PATCH 07/16] t/perf/p7519: cleanup coding style fixup! t/perf/p7519: add fsmonitor--daemon test cases Add "_hook" to name of shell function to set up for Watchman/hook test runs. Fix code style of added "if then". Add body of builtin test to a test_expect_success. Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/perf/p7519-fsmonitor.sh | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/t/perf/p7519-fsmonitor.sh b/t/perf/p7519-fsmonitor.sh index 5f97edf6a113b5..7a7981b0e614a1 100755 --- a/t/perf/p7519-fsmonitor.sh +++ b/t/perf/p7519-fsmonitor.sh @@ -141,7 +141,7 @@ test_expect_success "one time repo setup" ' fi ' -setup_for_fsmonitor () { +setup_for_fsmonitor_hook () { # set INTEGRATION_SCRIPT depending on the environment if test -n "$INTEGRATION_PATH" then @@ -182,8 +182,7 @@ test_perf_w_drop_caches () { } test_fsmonitor_suite () { - if test -n "$USE_FSMONITOR_DAEMON" - then + if test -n "$USE_FSMONITOR_DAEMON"; then DESC="builtin fsmonitor--daemon" elif test -n "$INTEGRATION_SCRIPT"; then DESC="fsmonitor=$(basename $INTEGRATION_SCRIPT)" @@ -264,11 +263,11 @@ test_fsmonitor_suite () { trace_start fsmonitor-watchman if test -n "$GIT_PERF_7519_FSMONITOR"; then for INTEGRATION_PATH in $GIT_PERF_7519_FSMONITOR; do - test_expect_success "setup for fsmonitor $INTEGRATION_PATH" 'setup_for_fsmonitor' + test_expect_success "setup for fsmonitor $INTEGRATION_PATH" 'setup_for_fsmonitor_hook' test_fsmonitor_suite done else - test_expect_success "setup for fsmonitor" 'setup_for_fsmonitor' + test_expect_success "setup for fsmonitor hook" 'setup_for_fsmonitor_hook' test_fsmonitor_suite fi @@ -306,13 +305,15 @@ if test_have_prereq FSMONITOR_DAEMON then USE_FSMONITOR_DAEMON=t - trace_start fsmonitor--daemon--server - git fsmonitor--daemon start + test_expect_success "setup for builtin fsmonitor" ' + trace_start fsmonitor--daemon--server && + git fsmonitor--daemon start && - trace_start fsmonitor--daemon--client + trace_start fsmonitor--daemon--client && - git config core.fsmonitor true - git update-index --fsmonitor + git config core.fsmonitor true && + git update-index --fsmonitor + ' test_fsmonitor_suite From 5168c76dc0032712db822fb76b6a20d8f0418851 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:55 +0000 Subject: [PATCH 08/16] t7527: add parameters to start_daemon to handle args and subshell fixup! t7527: create test for fsmonitor--daemon Add parameters to start_daemon() and handle subshell and logging args. Remove /dev/null from commands. Fix &&-chaining of functions. Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/t7527-builtin-fsmonitor.sh | 217 ++++++++++++++++++----------------- 1 file changed, 111 insertions(+), 106 deletions(-) diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index 0ccbfb9616f635..026382a0d866e1 100755 --- a/t/t7527-builtin-fsmonitor.sh +++ b/t/t7527-builtin-fsmonitor.sh @@ -11,30 +11,85 @@ then fi stop_daemon_delete_repo () { - r=$1 - git -C $r fsmonitor--daemon stop >/dev/null 2>/dev/null + r=$1 && + test_might_fail git -C $r fsmonitor--daemon stop && rm -rf $1 - return 0 } start_daemon () { - case "$#" in - 1) r="-C $1";; - *) r=""; - esac + r="" && + tf="" && + t2="" && + tk="" && - git $r fsmonitor--daemon start || return $? - git $r fsmonitor--daemon status || return $? + while test "$#" -ne 0 + do + case "$1" in + -C) + shift; + test "$#" -ne 0 || + { echo >&2 "error: -C requires arg"; exit 1; } + r="-C $1" + shift + ;; + -tf) + shift; + test "$#" -ne 0 || + { echo >&2 "error: -tf requires arg"; exit 1; } + tf="$1" + shift + ;; + -t2) + shift; + test "$#" -ne 0 || + { echo >&2 "error: -t2 requires arg"; exit 1; } + t2="$1" + shift + ;; + -tk) + shift; + test "$#" -ne 0 || + { echo >&2 "error: -tk requires arg"; exit 1; } + tk="$1" + shift + ;; + *) + echo >&2 "error: unknown option: '$1'" + exit 1 + ;; + esac + done && + + ( + if test ! -z "$tf" + then + GIT_TRACE_FSMONITOR="$tf" + export GIT_TRACE_FSMONITOR + fi && + + if test ! -z "$t2" + then + GIT_TRACE2_PERF="$t2" + export GIT_TRACE2_PERF + fi && + + if test ! -z "$tk" + then + GIT_TEST_FSMONITOR_TOKEN="$tk" + export GIT_TEST_FSMONITOR_TOKEN + fi && - return 0 + git $r fsmonitor--daemon start && + git $r fsmonitor--daemon status + ) } # Is a Trace2 data event present with the given catetory and key? # We do not care what the value is. # have_t2_data_event () { - c=$1 - k=$2 + c=$1 && + k=$2 && grep -e '"event":"data".*"category":"'"$c"'".*"key":"'"$k"'"' } @@ -43,7 +98,7 @@ test_expect_success 'explicit daemon start and stop' ' test_when_finished "stop_daemon_delete_repo test_explicit" && git init test_explicit && - start_daemon test_explicit && + start_daemon -C test_explicit && git -C test_explicit fsmonitor--daemon stop && test_must_fail git -C test_explicit fsmonitor--daemon status @@ -63,7 +118,7 @@ test_expect_success 'implicit daemon start' ' # but this test case is only concerned with whether the daemon was # implicitly started.) - GIT_TRACE2_EVENT="$(pwd)/.git/trace" \ + GIT_TRACE2_EVENT="$PWD/.git/trace" \ test-tool -C test_implicit fsmonitor-client query --token 0 >actual && nul_to_q actual.filtered && grep "builtin:" actual.filtered && @@ -86,7 +141,7 @@ test_expect_success 'implicit daemon stop (delete .git)' ' git init test_implicit_1 && - start_daemon test_implicit_1 && + start_daemon -C test_implicit_1 && # deleting the .git directory will implicitly stop the daemon. rm -rf test_implicit_1/.git && @@ -110,7 +165,7 @@ test_expect_success 'implicit daemon stop (rename .git)' ' git init test_implicit_2 && - start_daemon test_implicit_2 && + start_daemon -C test_implicit_2 && # renaming the .git directory will implicitly stop the daemon. mv test_implicit_2/.git test_implicit_2/.xxx && @@ -128,7 +183,7 @@ test_expect_success 'cannot start multiple daemons' ' git init test_multiple && - start_daemon test_multiple && + start_daemon -C test_multiple && test_must_fail git -C test_multiple fsmonitor--daemon start 2>actual && grep "fsmonitor--daemon is already running" actual && @@ -177,8 +232,7 @@ test_expect_success 'setup' ' # This is here in case something else fails first. # redundant_stop_daemon () { - git fsmonitor--daemon stop - return 0 + test_might_fail git fsmonitor--daemon stop } test_expect_success 'update-index implicitly starts daemon' ' @@ -186,7 +240,7 @@ test_expect_success 'update-index implicitly starts daemon' ' test_must_fail git fsmonitor--daemon status && - GIT_TRACE2_EVENT="$(pwd)/.git/trace_implicit_1" \ + GIT_TRACE2_EVENT="$PWD/.git/trace_implicit_1" \ git update-index --fsmonitor && git fsmonitor--daemon status && @@ -202,7 +256,7 @@ test_expect_success 'status implicitly starts daemon' ' test_must_fail git fsmonitor--daemon status && - GIT_TRACE2_EVENT="$(pwd)/.git/trace_implicit_2" \ + GIT_TRACE2_EVENT="$PWD/.git/trace_implicit_2" \ git status >actual && git fsmonitor--daemon status && @@ -214,38 +268,38 @@ test_expect_success 'status implicitly starts daemon' ' ' edit_files () { - echo 1 >modified - echo 2 >dir1/modified - echo 3 >dir2/modified + echo 1 >modified && + echo 2 >dir1/modified && + echo 3 >dir2/modified && >dir1/untracked } delete_files () { - rm -f delete - rm -f dir1/delete + rm -f delete && + rm -f dir1/delete && rm -f dir2/delete } create_files () { - echo 1 >new - echo 2 >dir1/new + echo 1 >new && + echo 2 >dir1/new && echo 3 >dir2/new } rename_files () { - mv rename renamed - mv dir1/rename dir1/renamed + mv rename renamed && + mv dir1/rename dir1/renamed && mv dir2/rename dir2/renamed } file_to_directory () { - rm -f delete - mkdir delete + rm -f delete && + mkdir delete && echo 1 >delete/new } directory_to_file () { - rm -rf dir1 + rm -rf dir1 && echo 1 >dir1 } @@ -272,25 +326,20 @@ verify_status () { # daemon) because these commands might implicitly restart the daemon. clean_up_repo_and_stop_daemon () { - git reset --hard HEAD - git clean -fd - git fsmonitor--daemon stop + git reset --hard HEAD && + git clean -fd && + test_might_fail git fsmonitor--daemon stop && rm -f .git/trace } test_expect_success 'edit some files' ' test_when_finished clean_up_repo_and_stop_daemon && - ( - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace" && - export GIT_TRACE_FSMONITOR && - - start_daemon - ) && + start_daemon -tf "$PWD/.git/trace" && edit_files && - test-tool fsmonitor-client query --token 0 >/dev/null 2>&1 && + test-tool fsmonitor-client query --token 0 && grep "^event: dir1/modified$" .git/trace && grep "^event: dir2/modified$" .git/trace && @@ -301,16 +350,11 @@ test_expect_success 'edit some files' ' test_expect_success 'create some files' ' test_when_finished clean_up_repo_and_stop_daemon && - ( - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace" && - export GIT_TRACE_FSMONITOR && - - start_daemon - ) && + start_daemon -tf "$PWD/.git/trace" && create_files && - test-tool fsmonitor-client query --token 0 >/dev/null 2>&1 && + test-tool fsmonitor-client query --token 0 && grep "^event: dir1/new$" .git/trace && grep "^event: dir2/new$" .git/trace && @@ -320,16 +364,11 @@ test_expect_success 'create some files' ' test_expect_success 'delete some files' ' test_when_finished clean_up_repo_and_stop_daemon && - ( - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace" && - export GIT_TRACE_FSMONITOR && - - start_daemon - ) && + start_daemon -tf "$PWD/.git/trace" && delete_files && - test-tool fsmonitor-client query --token 0 >/dev/null 2>&1 && + test-tool fsmonitor-client query --token 0 && grep "^event: dir1/delete$" .git/trace && grep "^event: dir2/delete$" .git/trace && @@ -339,16 +378,11 @@ test_expect_success 'delete some files' ' test_expect_success 'rename some files' ' test_when_finished clean_up_repo_and_stop_daemon && - ( - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace" && - export GIT_TRACE_FSMONITOR && - - start_daemon - ) && + start_daemon -tf "$PWD/.git/trace" && rename_files && - test-tool fsmonitor-client query --token 0 >/dev/null 2>&1 && + test-tool fsmonitor-client query --token 0 && grep "^event: dir1/rename$" .git/trace && grep "^event: dir2/rename$" .git/trace && @@ -361,16 +395,11 @@ test_expect_success 'rename some files' ' test_expect_success 'rename directory' ' test_when_finished clean_up_repo_and_stop_daemon && - ( - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace" && - export GIT_TRACE_FSMONITOR && - - start_daemon - ) && + start_daemon -tf "$PWD/.git/trace" && mv dirtorename dirrenamed && - test-tool fsmonitor-client query --token 0 >/dev/null 2>&1 && + test-tool fsmonitor-client query --token 0 && grep "^event: dirtorename/*$" .git/trace && grep "^event: dirrenamed/*$" .git/trace @@ -379,16 +408,11 @@ test_expect_success 'rename directory' ' test_expect_success 'file changes to directory' ' test_when_finished clean_up_repo_and_stop_daemon && - ( - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace" && - export GIT_TRACE_FSMONITOR && - - start_daemon - ) && + start_daemon -tf "$PWD/.git/trace" && file_to_directory && - test-tool fsmonitor-client query --token 0 >/dev/null 2>&1 && + test-tool fsmonitor-client query --token 0 && grep "^event: delete$" .git/trace && grep "^event: delete/new$" .git/trace @@ -397,16 +421,11 @@ test_expect_success 'file changes to directory' ' test_expect_success 'directory changes to a file' ' test_when_finished clean_up_repo_and_stop_daemon && - ( - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace" && - export GIT_TRACE_FSMONITOR && - - start_daemon - ) && + start_daemon -tf "$PWD/.git/trace" && directory_to_file && - test-tool fsmonitor-client query --token 0 >/dev/null 2>&1 && + test-tool fsmonitor-client query --token 0 && grep "^event: dir1$" .git/trace ' @@ -424,15 +443,7 @@ test_expect_success 'flush cached data' ' git init test_flush && - ( - GIT_TEST_FSMONITOR_TOKEN=true && - export GIT_TEST_FSMONITOR_TOKEN && - - GIT_TRACE_FSMONITOR="$(pwd)/.git/trace_daemon" && - export GIT_TRACE_FSMONITOR && - - start_daemon test_flush - ) && + start_daemon -C test_flush -tf "$PWD/.git/trace_daemon" -tk true && # The daemon should have an initial token with no events in _0 and # then a few (probably platform-specific number of) events in _1. @@ -441,8 +452,8 @@ test_expect_success 'flush cached data' ' test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000001:0" >actual_0 && nul_to_q actual_q0 && - touch test_flush/file_1 && - touch test_flush/file_2 && + > test_flush/file_1 && + > test_flush/file_2 && test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000001:0" >actual_1 && nul_to_q actual_q1 && @@ -462,7 +473,7 @@ test_expect_success 'flush cached data' ' grep "^builtin:test_00000002:0Q$" actual_q2 && - touch test_flush/file_3 && + > test_flush/file_3 && test-tool -C test_flush fsmonitor-client query --token "builtin:test_00000002:0" >actual_3 && nul_to_q actual_q3 && @@ -485,15 +496,9 @@ test_expect_success 'setup worktree base' ' test_expect_success 'worktree with .git file' ' git -C wt-base worktree add ../wt-secondary && - ( - GIT_TRACE2_PERF="$(pwd)/trace2_wt_secondary" && - export GIT_TRACE2_PERF && - - GIT_TRACE_FSMONITOR="$(pwd)/trace_wt_secondary" && - export GIT_TRACE_FSMONITOR && - - start_daemon wt-secondary - ) && + start_daemon -C wt-secondary \ + -tf "$PWD/trace_wt_secondary" \ + -t2 "$PWD/trace2_wt_secondary" && git -C wt-secondary fsmonitor--daemon stop && test_must_fail git -C wt-secondary fsmonitor--daemon status From d71c6b38c63fe7cdd89bae5e770e1551b5840274 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:56 +0000 Subject: [PATCH 09/16] t7527: fix && chaining in matrix_try() fixup! t7527: test status with untracked-cache and fsmonitor--daemon Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/t7527-builtin-fsmonitor.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index 026382a0d866e1..f60e211dbab8a6 100755 --- a/t/t7527-builtin-fsmonitor.sh +++ b/t/t7527-builtin-fsmonitor.sh @@ -536,9 +536,9 @@ matrix_clean_up_repo () { } matrix_try () { - uc=$1 - fsm=$2 - fn=$3 + uc=$1 && + fsm=$2 && + fn=$3 && test_expect_success "Matrix[uc:$uc][fsm:$fsm] $fn" ' matrix_clean_up_repo && From 9b4e8812a98102878e87e669d76cde4c0a49ffda Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:57 +0000 Subject: [PATCH 10/16] t7527: delete unused verify_status() function fixup! t7527: create test for fsmonitor--daemon Remove unused function verify_status(). Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/t7527-builtin-fsmonitor.sh | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index f60e211dbab8a6..ef8777e7f6d4a5 100755 --- a/t/t7527-builtin-fsmonitor.sh +++ b/t/t7527-builtin-fsmonitor.sh @@ -303,16 +303,6 @@ directory_to_file () { echo 1 >dir1 } -verify_status () { - git status >actual && - GIT_INDEX_FILE=.git/fresh-index git read-tree master && - GIT_INDEX_FILE=.git/fresh-index git -c core.fsmonitor=false status >expect && - test_cmp expect actual && - echo HELLO AFTER && - cat .git/trace && - echo HELLO AFTER -} - # The next few test cases confirm that our fsmonitor daemon sees each type # of OS filesystem notification that we care about. At this layer we just # ensure we are getting the OS notifications and do not try to confirm what From 4a50a37c3a1a987c7c3e5adbaf76c4d65432558e Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:58 +0000 Subject: [PATCH 11/16] fsmonitor-ipc: add _() to calls to die() fixup! fsmonitor-ipc: create client routines for git-fsmonitor--daemon Fix translation markings. Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- fsmonitor-ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fsmonitor-ipc.c b/fsmonitor-ipc.c index 91a535f1219b5a..789e7397baa48d 100644 --- a/fsmonitor-ipc.c +++ b/fsmonitor-ipc.c @@ -152,7 +152,7 @@ int fsmonitor_ipc__send_command(const char *command, state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options, &connection); if (state != IPC_STATE__LISTENING) { - die("fsmonitor--daemon is not running"); + die(_("fsmonitor--daemon is not running")); return -1; } @@ -161,7 +161,7 @@ int fsmonitor_ipc__send_command(const char *command, ipc_client_close_connection(connection); if (ret == -1) { - die("could not send '%s' command to fsmonitor--daemon", c); + die(_("could not send '%s' command to fsmonitor--daemon"), c); return -1; } From 1093f99f4d0d1e38d543f5e89b3184494227afd2 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:14:59 +0000 Subject: [PATCH 12/16] compat/fsmonitor/fsm-listen-darwin: add _() to calls to error() fixup! compat/fsmonitor/fsm-listen-darwin: implement FSEvent listener \ on MacOS Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- compat/fsmonitor/fsm-listen-darwin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c index 9a73fb607d5b2c..d9d0d0fa0e94fd 100644 --- a/compat/fsmonitor/fsm-listen-darwin.c +++ b/compat/fsmonitor/fsm-listen-darwin.c @@ -335,7 +335,7 @@ int fsm_listen__ctor(struct fsmonitor_daemon_state *state) return 0; failed: - error("Unable to create FSEventStream."); + error(_("Unable to create FSEventStream.")); FREE_AND_NULL(state->backend_data); return -1; @@ -383,7 +383,7 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state) data->stream_scheduled = 1; if (!FSEventStreamStart(data->stream)) { - error("Failed to start the FSEventStream"); + error(_("Failed to start the FSEventStream")); goto force_error_stop_without_loop; } data->stream_started = 1; From 358d0e57a9a26cee92515c0a4f5aa1a7de2627d1 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:15:00 +0000 Subject: [PATCH 13/16] compat/fsmonitor/fsm-listen-win32: add _() to calls to error() fixup! compat/fsmonitor/fsm-listen-win32: implement FSMonitor backend \ on Windows Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- compat/fsmonitor/fsm-listen-win32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compat/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c index c2d11acbc1ef7d..5b928ab66e5e71 100644 --- a/compat/fsmonitor/fsm-listen-win32.c +++ b/compat/fsmonitor/fsm-listen-win32.c @@ -82,7 +82,7 @@ static int normalize_path_in_utf8(FILE_NOTIFY_INFORMATION *info, if (len > 0) goto normalize; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - error("[GLE %ld] could not convert path to UTF-8: '%.*ls'", + error(_("[GLE %ld] could not convert path to UTF-8: '%.*ls'"), GetLastError(), (int)(info->FileNameLength / sizeof(WCHAR)), info->FileName); @@ -185,7 +185,7 @@ static int start_rdcw_watch(struct fsmonitor_daemon_backend_data *data, if (watch->is_active) return 0; - error("ReadDirectoryChangedW failed on '%s' [GLE %ld]", + error(_("ReadDirectoryChangedW failed on '%s' [GLE %ld]"), watch->path.buf, GetLastError()); return -1; } @@ -228,7 +228,7 @@ static int recv_rdcw_watch(struct one_watch *watch) * sure it is worth it. */ - error("GetOverlappedResult failed on '%s' [GLE %ld]", + error(_("GetOverlappedResult failed on '%s' [GLE %ld]"), watch->path.buf, gle); return -1; } From f373dcc3dd575d4a9e10bda6be3d3237f4e5b27c Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:15:01 +0000 Subject: [PATCH 14/16] fsmonitor--daemon: add _() to calls to die() fixup! fsmonitor--daemon: implement 'run' command Fix translation marking on die(). Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- builtin/fsmonitor--daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 02a99ce98a2508..b3687a200efefc 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -1326,7 +1326,7 @@ static int try_to_run_foreground_daemon(int detach_console) * common error case. */ if (fsmonitor_ipc__get_state() == IPC_STATE__LISTENING) - die("fsmonitor--daemon is already running '%s'", + die(_("fsmonitor--daemon is already running '%s'"), the_repository->worktree); if (fsmonitor__announce_startup) { From cf2d3f46e216a9325e5eb2369202dcb6a2fbfbd9 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:15:02 +0000 Subject: [PATCH 15/16] fsmonitor--daemon: add _() to calls to error() fixup! fsmonitor--daemon: implement 'start' command Fixup translation on die(). Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- builtin/fsmonitor--daemon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index b3687a200efefc..a30ecf6cfaccb2 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -1381,7 +1381,7 @@ static int try_to_start_background_daemon(void) * immediately exited). */ if (fsmonitor_ipc__get_state() == IPC_STATE__LISTENING) - die("fsmonitor--daemon is already running '%s'", + die(_("fsmonitor--daemon is already running '%s'"), the_repository->worktree); if (fsmonitor__announce_startup) { @@ -1411,13 +1411,13 @@ static int try_to_start_background_daemon(void) default: case SBGR_ERROR: case SBGR_CB_ERROR: - return error("daemon failed to start"); + return error(_("daemon failed to start")); case SBGR_TIMEOUT: - return error("daemon not online yet"); + return error(_("daemon not online yet")); case SBGR_DIED: - return error("daemon terminated"); + return error(_("daemon terminated")); } } From 7e19fac527ed9f12e9538e2fc2db9adc0a4e1050 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 11 Mar 2022 21:15:03 +0000 Subject: [PATCH 16/16] fsmonitor-settings: simplify initialization of settings data fixup! fsmonitor: config settings are repository-specific Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- fsmonitor-settings.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c index 3b54e7a51f6293..757d230d538056 100644 --- a/fsmonitor-settings.c +++ b/fsmonitor-settings.c @@ -22,11 +22,10 @@ static void lookup_fsmonitor_settings(struct repository *r) return; CALLOC_ARRAY(s, 1); + s->mode = FSMONITOR_MODE_DISABLED; r->settings.fsmonitor = s; - fsm_settings__set_disabled(r); - /* * Overload the existing "core.fsmonitor" config setting (which * has historically been either unset or a hook pathname) to