]> git.ipfire.org Git - thirdparty/git.git/blame - fsmonitor-ipc.c
Merge branch 'maint-2.36' into maint-2.37
[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
21const char *fsmonitor_ipc__get_path(void)
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
50GIT_PATH_FUNC(fsmonitor_ipc__get_path, "fsmonitor--daemon.ipc")
51
52enum ipc_active_state fsmonitor_ipc__get_state(void)
53{
54 return ipc_get_active_state(fsmonitor_ipc__get_path());
55}
56
57static int spawn_daemon(void)
58{
59 const char *args[] = { "fsmonitor--daemon", "start", NULL };
60
61 return run_command_v_opt_tr2(args, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD,
62 "fsmonitor");
63}
64
65int fsmonitor_ipc__send_query(const char *since_token,
66 struct strbuf *answer)
67{
68 int ret = -1;
69 int tried_to_spawn = 0;
70 enum ipc_active_state state = IPC_STATE__OTHER_ERROR;
71 struct ipc_client_connection *connection = NULL;
72 struct ipc_client_connect_options options
73 = IPC_CLIENT_CONNECT_OPTIONS_INIT;
74 const char *tok = since_token ? since_token : "";
75 size_t tok_len = since_token ? strlen(since_token) : 0;
76
77 options.wait_if_busy = 1;
78 options.wait_if_not_found = 0;
79
80 trace2_region_enter("fsm_client", "query", NULL);
81 trace2_data_string("fsm_client", NULL, "query/command", tok);
82
83try_again:
84 state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options,
85 &connection);
86
87 switch (state) {
88 case IPC_STATE__LISTENING:
89 ret = ipc_client_send_command_to_connection(
90 connection, tok, tok_len, answer);
91 ipc_client_close_connection(connection);
92
93 trace2_data_intmax("fsm_client", NULL,
94 "query/response-length", answer->len);
95 goto done;
96
97 case IPC_STATE__NOT_LISTENING:
98 case IPC_STATE__PATH_NOT_FOUND:
99 if (tried_to_spawn)
100 goto done;
101
102 tried_to_spawn++;
103 if (spawn_daemon())
104 goto done;
105
106 /*
107 * Try again, but this time give the daemon a chance to
108 * actually create the pipe/socket.
109 *
110 * Granted, the daemon just started so it can't possibly have
111 * any FS cached yet, so we'll always get a trivial answer.
112 * BUT the answer should include a new token that can serve
113 * as the basis for subsequent requests.
114 */
115 options.wait_if_not_found = 1;
116 goto try_again;
117
118 case IPC_STATE__INVALID_PATH:
119 ret = error(_("fsmonitor_ipc__send_query: invalid path '%s'"),
120 fsmonitor_ipc__get_path());
121 goto done;
122
123 case IPC_STATE__OTHER_ERROR:
124 default:
125 ret = error(_("fsmonitor_ipc__send_query: unspecified error on '%s'"),
126 fsmonitor_ipc__get_path());
127 goto done;
128 }
129
130done:
131 trace2_region_leave("fsm_client", "query", NULL);
132
133 return ret;
134}
135
136int fsmonitor_ipc__send_command(const char *command,
137 struct strbuf *answer)
138{
139 struct ipc_client_connection *connection = NULL;
140 struct ipc_client_connect_options options
141 = IPC_CLIENT_CONNECT_OPTIONS_INIT;
142 int ret;
143 enum ipc_active_state state;
144 const char *c = command ? command : "";
145 size_t c_len = command ? strlen(command) : 0;
146
147 strbuf_reset(answer);
148
149 options.wait_if_busy = 1;
150 options.wait_if_not_found = 0;
151
152 state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options,
153 &connection);
154 if (state != IPC_STATE__LISTENING) {
155 die(_("fsmonitor--daemon is not running"));
156 return -1;
157 }
158
159 ret = ipc_client_send_command_to_connection(connection, c, c_len,
160 answer);
161 ipc_client_close_connection(connection);
162
163 if (ret == -1) {
164 die(_("could not send '%s' command to fsmonitor--daemon"), c);
165 return -1;
166 }
167
168 return 0;
169}
170
171#endif