Git fork
at reftables-rust 176 lines 4.1 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2 3#include "git-compat-util.h" 4#include "gettext.h" 5#include "simple-ipc.h" 6#include "fsmonitor-ipc.h" 7#include "repository.h" 8#include "run-command.h" 9#include "strbuf.h" 10#include "trace2.h" 11 12#ifndef HAVE_FSMONITOR_DAEMON_BACKEND 13 14/* 15 * A trivial implementation of the fsmonitor_ipc__ API for unsupported 16 * platforms. 17 */ 18 19int fsmonitor_ipc__is_supported(void) 20{ 21 return 0; 22} 23 24const char *fsmonitor_ipc__get_path(struct repository *r UNUSED) 25{ 26 return NULL; 27} 28 29enum ipc_active_state fsmonitor_ipc__get_state(void) 30{ 31 return IPC_STATE__OTHER_ERROR; 32} 33 34int fsmonitor_ipc__send_query(const char *since_token UNUSED, 35 struct strbuf *answer UNUSED) 36{ 37 return -1; 38} 39 40int fsmonitor_ipc__send_command(const char *command UNUSED, 41 struct strbuf *answer UNUSED) 42{ 43 return -1; 44} 45 46#else 47 48int fsmonitor_ipc__is_supported(void) 49{ 50 return 1; 51} 52 53enum ipc_active_state fsmonitor_ipc__get_state(void) 54{ 55 return ipc_get_active_state(fsmonitor_ipc__get_path(the_repository)); 56} 57 58static int spawn_daemon(void) 59{ 60 struct child_process cmd = CHILD_PROCESS_INIT; 61 62 cmd.git_cmd = 1; 63 cmd.no_stdin = 1; 64 cmd.trace2_child_class = "fsmonitor"; 65 strvec_pushl(&cmd.args, "fsmonitor--daemon", "start", NULL); 66 67 return run_command(&cmd); 68} 69 70int fsmonitor_ipc__send_query(const char *since_token, 71 struct strbuf *answer) 72{ 73 int ret = -1; 74 int tried_to_spawn = 0; 75 enum ipc_active_state state = IPC_STATE__OTHER_ERROR; 76 struct ipc_client_connection *connection = NULL; 77 struct ipc_client_connect_options options 78 = IPC_CLIENT_CONNECT_OPTIONS_INIT; 79 const char *tok = since_token ? since_token : ""; 80 size_t tok_len = since_token ? strlen(since_token) : 0; 81 82 options.wait_if_busy = 1; 83 options.wait_if_not_found = 0; 84 85 trace2_region_enter("fsm_client", "query", NULL); 86 trace2_data_string("fsm_client", NULL, "query/command", tok); 87 88try_again: 89 state = ipc_client_try_connect(fsmonitor_ipc__get_path(the_repository), 90 &options, &connection); 91 92 switch (state) { 93 case IPC_STATE__LISTENING: 94 ret = ipc_client_send_command_to_connection( 95 connection, tok, tok_len, answer); 96 ipc_client_close_connection(connection); 97 98 trace2_data_intmax("fsm_client", NULL, 99 "query/response-length", answer->len); 100 goto done; 101 102 case IPC_STATE__NOT_LISTENING: 103 case IPC_STATE__PATH_NOT_FOUND: 104 if (tried_to_spawn) 105 goto done; 106 107 tried_to_spawn++; 108 if (spawn_daemon()) 109 goto done; 110 111 /* 112 * Try again, but this time give the daemon a chance to 113 * actually create the pipe/socket. 114 * 115 * Granted, the daemon just started so it can't possibly have 116 * any FS cached yet, so we'll always get a trivial answer. 117 * BUT the answer should include a new token that can serve 118 * as the basis for subsequent requests. 119 */ 120 options.wait_if_not_found = 1; 121 goto try_again; 122 123 case IPC_STATE__INVALID_PATH: 124 ret = error(_("fsmonitor_ipc__send_query: invalid path '%s'"), 125 fsmonitor_ipc__get_path(the_repository)); 126 goto done; 127 128 case IPC_STATE__OTHER_ERROR: 129 default: 130 ret = error(_("fsmonitor_ipc__send_query: unspecified error on '%s'"), 131 fsmonitor_ipc__get_path(the_repository)); 132 goto done; 133 } 134 135done: 136 trace2_region_leave("fsm_client", "query", NULL); 137 138 return ret; 139} 140 141int fsmonitor_ipc__send_command(const char *command, 142 struct strbuf *answer) 143{ 144 struct ipc_client_connection *connection = NULL; 145 struct ipc_client_connect_options options 146 = IPC_CLIENT_CONNECT_OPTIONS_INIT; 147 int ret; 148 enum ipc_active_state state; 149 const char *c = command ? command : ""; 150 size_t c_len = command ? strlen(command) : 0; 151 152 strbuf_reset(answer); 153 154 options.wait_if_busy = 1; 155 options.wait_if_not_found = 0; 156 157 state = ipc_client_try_connect(fsmonitor_ipc__get_path(the_repository), 158 &options, &connection); 159 if (state != IPC_STATE__LISTENING) { 160 die(_("fsmonitor--daemon is not running")); 161 return -1; 162 } 163 164 ret = ipc_client_send_command_to_connection(connection, c, c_len, 165 answer); 166 ipc_client_close_connection(connection); 167 168 if (ret == -1) { 169 die(_("could not send '%s' command to fsmonitor--daemon"), c); 170 return -1; 171 } 172 173 return 0; 174} 175 176#endif