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