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