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