git

Форк
0
/
fsmonitor-ipc.c 
176 строк · 4.0 Кб
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

19
int fsmonitor_ipc__is_supported(void)
20
{
21
	return 0;
22
}
23

24
const char *fsmonitor_ipc__get_path(struct repository *r UNUSED)
25
{
26
	return NULL;
27
}
28

29
enum ipc_active_state fsmonitor_ipc__get_state(void)
30
{
31
	return IPC_STATE__OTHER_ERROR;
32
}
33

34
int fsmonitor_ipc__send_query(const char *since_token UNUSED,
35
			      struct strbuf *answer UNUSED)
36
{
37
	return -1;
38
}
39

40
int fsmonitor_ipc__send_command(const char *command UNUSED,
41
				struct strbuf *answer UNUSED)
42
{
43
	return -1;
44
}
45

46
#else
47

48
int fsmonitor_ipc__is_supported(void)
49
{
50
	return 1;
51
}
52

53
enum ipc_active_state fsmonitor_ipc__get_state(void)
54
{
55
	return ipc_get_active_state(fsmonitor_ipc__get_path(the_repository));
56
}
57

58
static 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

70
int 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

88
try_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

135
done:
136
	trace2_region_leave("fsm_client", "query", NULL);
137

138
	return ret;
139
}
140

141
int 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
177

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.