mirror of
https://github.com/git-for-windows/git.git
synced 2026-03-16 19:41:56 -05:00
fsmonitor-ipc: create client routines for git-fsmonitor--daemon
Create client routines to spawn a fsmonitor daemon and send it an IPC request using `simple-ipc`. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
This commit is contained in:
committed by
Johannes Schindelin
parent
31495df8a9
commit
7db58bc558
1
Makefile
1
Makefile
@@ -893,6 +893,7 @@ LIB_OBJS += fetch-pack.o
|
||||
LIB_OBJS += fmt-merge-msg.o
|
||||
LIB_OBJS += fsck.o
|
||||
LIB_OBJS += fsmonitor.o
|
||||
LIB_OBJS += fsmonitor-ipc.o
|
||||
LIB_OBJS += gettext.o
|
||||
LIB_OBJS += gpg-interface.o
|
||||
LIB_OBJS += graph.o
|
||||
|
||||
153
fsmonitor-ipc.c
Normal file
153
fsmonitor-ipc.c
Normal file
@@ -0,0 +1,153 @@
|
||||
#include "cache.h"
|
||||
#include "fsmonitor.h"
|
||||
#include "fsmonitor-ipc.h"
|
||||
#include "run-command.h"
|
||||
#include "strbuf.h"
|
||||
#include "trace2.h"
|
||||
|
||||
#ifdef HAVE_FSMONITOR_DAEMON_BACKEND
|
||||
#define FSMONITOR_DAEMON_IS_SUPPORTED 1
|
||||
#else
|
||||
#define FSMONITOR_DAEMON_IS_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A trivial function so that this source file always defines at least
|
||||
* one symbol even when the feature is not supported. This quiets an
|
||||
* annoying compiler error.
|
||||
*/
|
||||
int fsmonitor_ipc__is_supported(void)
|
||||
{
|
||||
return FSMONITOR_DAEMON_IS_SUPPORTED;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FSMONITOR_DAEMON_BACKEND
|
||||
|
||||
GIT_PATH_FUNC(fsmonitor_ipc__get_path, "fsmonitor")
|
||||
|
||||
enum ipc_active_state fsmonitor_ipc__get_state(void)
|
||||
{
|
||||
return ipc_get_active_state(fsmonitor_ipc__get_path());
|
||||
}
|
||||
|
||||
static int spawn_daemon(void)
|
||||
{
|
||||
const char *args[] = { "fsmonitor--daemon", "--start", NULL };
|
||||
|
||||
return run_command_v_opt_tr2(args, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD,
|
||||
"fsmonitor");
|
||||
}
|
||||
|
||||
int fsmonitor_ipc__send_query(const char *since_token,
|
||||
struct strbuf *answer)
|
||||
{
|
||||
int ret = -1;
|
||||
int tried_to_spawn = 0;
|
||||
enum ipc_active_state state = IPC_STATE__OTHER_ERROR;
|
||||
struct ipc_client_connection *connection = NULL;
|
||||
struct ipc_client_connect_options options
|
||||
= IPC_CLIENT_CONNECT_OPTIONS_INIT;
|
||||
|
||||
options.wait_if_busy = 1;
|
||||
options.wait_if_not_found = 0;
|
||||
|
||||
trace2_region_enter("fsm_client", "query", NULL);
|
||||
|
||||
trace2_data_string("fsm_client", NULL, "query/command",
|
||||
since_token);
|
||||
|
||||
try_again:
|
||||
state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options,
|
||||
&connection);
|
||||
|
||||
switch (state) {
|
||||
case IPC_STATE__LISTENING:
|
||||
ret = ipc_client_send_command_to_connection(
|
||||
connection, since_token, answer);
|
||||
ipc_client_close_connection(connection);
|
||||
|
||||
trace2_data_intmax("fsm_client", NULL,
|
||||
"query/response-length", answer->len);
|
||||
|
||||
if (fsmonitor_is_trivial_response(answer))
|
||||
trace2_data_intmax("fsm_client", NULL,
|
||||
"query/trivial-response", 1);
|
||||
|
||||
goto done;
|
||||
|
||||
case IPC_STATE__NOT_LISTENING:
|
||||
ret = error(_("fsmonitor_ipc__send_query: daemon not available"));
|
||||
goto done;
|
||||
|
||||
case IPC_STATE__PATH_NOT_FOUND:
|
||||
if (tried_to_spawn)
|
||||
goto done;
|
||||
|
||||
tried_to_spawn++;
|
||||
if (spawn_daemon())
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Try again, but this time give the daemon a chance to
|
||||
* actually create the pipe/socket.
|
||||
*
|
||||
* Granted, the daemon just started so it can't possibly have
|
||||
* any FS cached yet, so we'll always get a trivial answer.
|
||||
* BUT the answer should include a new token that can serve
|
||||
* as the basis for subsequent requests.
|
||||
*/
|
||||
options.wait_if_not_found = 1;
|
||||
goto try_again;
|
||||
|
||||
case IPC_STATE__INVALID_PATH:
|
||||
ret = error(_("fsmonitor_ipc__send_query: invalid path '%s'"),
|
||||
fsmonitor_ipc__get_path());
|
||||
goto done;
|
||||
|
||||
case IPC_STATE__OTHER_ERROR:
|
||||
default:
|
||||
ret = error(_("fsmonitor_ipc__send_query: unspecified error on '%s'"),
|
||||
fsmonitor_ipc__get_path());
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
trace2_region_leave("fsm_client", "query", NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fsmonitor_ipc__send_command(const char *command,
|
||||
struct strbuf *answer)
|
||||
{
|
||||
struct ipc_client_connection *connection = NULL;
|
||||
struct ipc_client_connect_options options
|
||||
= IPC_CLIENT_CONNECT_OPTIONS_INIT;
|
||||
int ret;
|
||||
enum ipc_active_state state;
|
||||
|
||||
strbuf_reset(answer);
|
||||
|
||||
options.wait_if_busy = 1;
|
||||
options.wait_if_not_found = 0;
|
||||
|
||||
state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options,
|
||||
&connection);
|
||||
if (state != IPC_STATE__LISTENING) {
|
||||
die("fsmonitor--daemon is not running");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ipc_client_send_command_to_connection(connection, command, answer);
|
||||
ipc_client_close_connection(connection);
|
||||
|
||||
if (ret == -1) {
|
||||
die("could not send '%s' command to fsmonitor--daemon",
|
||||
command);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
48
fsmonitor-ipc.h
Normal file
48
fsmonitor-ipc.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef FSMONITOR_IPC_H
|
||||
#define FSMONITOR_IPC_H
|
||||
|
||||
/*
|
||||
* Returns true if a filesystem notification backend is defined
|
||||
* for this platform. This symbol must always be visible and
|
||||
* outside of the HAVE_ ifdef.
|
||||
*/
|
||||
int fsmonitor_ipc__is_supported(void);
|
||||
|
||||
#ifdef HAVE_FSMONITOR_DAEMON_BACKEND
|
||||
#include "run-command.h"
|
||||
#include "simple-ipc.h"
|
||||
|
||||
/*
|
||||
* Returns the pathname to the IPC named pipe or Unix domain socket
|
||||
* where a `git-fsmonitor--daemon` process will listen. This is a
|
||||
* per-worktree value.
|
||||
*/
|
||||
const char *fsmonitor_ipc__get_path(void);
|
||||
|
||||
/*
|
||||
* Try to determine whether there is a `git-fsmonitor--daemon` process
|
||||
* listening on the IPC pipe/socket.
|
||||
*/
|
||||
enum ipc_active_state fsmonitor_ipc__get_state(void);
|
||||
|
||||
/*
|
||||
* Connect to a `git-fsmonitor--daemon` process via simple-ipc
|
||||
* and ask for the set of changed files since the given token.
|
||||
*
|
||||
* This DOES NOT use the hook interface.
|
||||
*
|
||||
* Spawn a daemon process in the background if necessary.
|
||||
*/
|
||||
int fsmonitor_ipc__send_query(const char *since_token,
|
||||
struct strbuf *answer);
|
||||
|
||||
/*
|
||||
* Connect to a `git-fsmonitor--daemon` process via simple-ipc and
|
||||
* send a command verb. If no daemon is available, we DO NOT try to
|
||||
* start one.
|
||||
*/
|
||||
int fsmonitor_ipc__send_command(const char *command,
|
||||
struct strbuf *answer);
|
||||
|
||||
#endif /* HAVE_FSMONITOR_DAEMON_BACKEND */
|
||||
#endif /* FSMONITOR_IPC_H */
|
||||
4
help.c
4
help.c
@@ -11,6 +11,7 @@
|
||||
#include "version.h"
|
||||
#include "refs.h"
|
||||
#include "parse-options.h"
|
||||
#include "fsmonitor-ipc.h"
|
||||
|
||||
struct category_description {
|
||||
uint32_t category;
|
||||
@@ -664,6 +665,9 @@ void get_version_info(struct strbuf *buf, int show_build_options)
|
||||
strbuf_addf(buf, "sizeof-size_t: %d\n", (int)sizeof(size_t));
|
||||
strbuf_addf(buf, "shell-path: %s\n", SHELL_PATH);
|
||||
/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
|
||||
|
||||
if (fsmonitor_ipc__is_supported())
|
||||
strbuf_addstr(buf, "feature: fsmonitor--daemon\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user