@matheusbsbs / matheus-bagliano / commits / bf3c523c3f
Fork 0

Add remote helper debug mode

Remote helpers deadlock easily, so support debug mode which shows the interaction steps. Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ilari Liusvaara committed Dec 9, 2009 at 17:26 UTC bf3c523c3fd641609adcef67dcec47a43a6abd60
1 file changed +69 -25
transport-helper.c
+69 -25
@@ -8,6 +8,8 @@
8 #include "quote.h"
9 #include "remote.h"
10
11 +static int debug;
12 +
13 struct helper_data
14 {
15 const char *name;
@@ -22,6 +24,45 @@ struct helper_data
24 int refspec_nr;
25 };
26
27 +static void sendline(struct helper_data *helper, struct strbuf *buffer)
28 +{
29 + if (debug)
30 + fprintf(stderr, "Debug: Remote helper: -> %s", buffer->buf);
31 + if (write_in_full(helper->helper->in, buffer->buf, buffer->len)
32 + != buffer->len)
33 + die_errno("Full write to remote helper failed");
34 +}
35 +
36 +static int recvline(struct helper_data *helper, struct strbuf *buffer)
37 +{
38 + strbuf_reset(buffer);
39 + if (debug)
40 + fprintf(stderr, "Debug: Remote helper: Waiting...\n");
41 + if (strbuf_getline(buffer, helper->out, '\n') == EOF) {
42 + if (debug)
43 + fprintf(stderr, "Debug: Remote helper quit.\n");
44 + exit(128);
45 + }
46 +
47 + if (debug)
48 + fprintf(stderr, "Debug: Remote helper: <- %s\n", buffer->buf);
49 + return 0;
50 +}
51 +
52 +static void xchgline(struct helper_data *helper, struct strbuf *buffer)
53 +{
54 + sendline(helper, buffer);
55 + recvline(helper, buffer);
56 +}
57 +
58 +static void write_constant(int fd, const char *str)
59 +{
60 + if (debug)
61 + fprintf(stderr, "Debug: Remote helper: -> %s", str);
62 + if (write_in_full(fd, str, strlen(str)) != strlen(str))
63 + die_errno("Full write to remote helper failed");
64 +}
65 +
66 static struct child_process *get_helper(struct transport *transport)
67 {
68 struct helper_data *data = transport->data;
@@ -48,15 +89,16 @@ static struct child_process *get_helper(struct transport *transport)
89 die("Unable to run helper: git %s", helper->argv[0]);
90 data->helper = helper;
91
51 - write_str_in_full(helper->in, "capabilities\n");
92 + write_constant(helper->in, "capabilities\n");
93
94 data->out = xfdopen(helper->out, "r");
95 while (1) {
55 - if (strbuf_getline(&buf, data->out, '\n') == EOF)
56 - exit(128); /* child died, message supplied already */
96 + recvline(data, &buf);
97
98 if (!*buf.buf)
99 break;
100 + if (debug)
101 + fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
102 if (!strcmp(buf.buf, "fetch"))
103 data->fetch = 1;
104 if (!strcmp(buf.buf, "option"))
@@ -82,14 +124,21 @@ static struct child_process *get_helper(struct transport *transport)
124 free(refspecs);
125 }
126 strbuf_release(&buf);
127 + if (debug)
128 + fprintf(stderr, "Debug: Capabilities complete.\n");
129 return data->helper;
130 }
131
132 static int disconnect_helper(struct transport *transport)
133 {
134 struct helper_data *data = transport->data;
135 + struct strbuf buf = STRBUF_INIT;
136 +
137 if (data->helper) {
92 - write_str_in_full(data->helper->in, "\n");
138 + if (debug)
139 + fprintf(stderr, "Debug: Disconnecting.\n");
140 + strbuf_addf(&buf, "\n");
141 + sendline(data, &buf);
142 close(data->helper->in);
143 fclose(data->out);
144 finish_command(data->helper);
@@ -117,10 +166,11 @@ static int set_helper_option(struct transport *transport,
166 const char *name, const char *value)
167 {
168 struct helper_data *data = transport->data;
120 - struct child_process *helper = get_helper(transport);
169 struct strbuf buf = STRBUF_INIT;
170 int i, ret, is_bool = 0;
171
172 + get_helper(transport);
173 +
174 if (!data->option)
175 return 1;
176
@@ -143,12 +193,7 @@ static int set_helper_option(struct transport *transport,
193 quote_c_style(value, &buf, NULL, 0);
194 strbuf_addch(&buf, '\n');
195
146 - if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
147 - die_errno("cannot send option to %s", data->name);
148 -
149 - strbuf_reset(&buf);
150 - if (strbuf_getline(&buf, data->out, '\n') == EOF)
151 - exit(128); /* child died, message supplied already */
196 + xchgline(data, &buf);
197
198 if (!strcmp(buf.buf, "ok"))
199 ret = 0;
@@ -208,13 +253,10 @@ static int fetch_with_fetch(struct transport *transport,
253 }
254
255 strbuf_addch(&buf, '\n');
211 - if (write_in_full(data->helper->in, buf.buf, buf.len) != buf.len)
212 - die_errno("cannot send fetch to %s", data->name);
256 + sendline(data, &buf);
257
258 while (1) {
215 - strbuf_reset(&buf);
216 - if (strbuf_getline(&buf, data->out, '\n') == EOF)
217 - exit(128); /* child died, message supplied already */
259 + recvline(data, &buf);
260
261 if (!prefixcmp(buf.buf, "lock ")) {
262 const char *name = buf.buf + 5;
@@ -249,12 +291,13 @@ static int fetch_with_import(struct transport *transport,
291 int nr_heads, struct ref **to_fetch)
292 {
293 struct child_process fastimport;
252 - struct child_process *helper = get_helper(transport);
294 struct helper_data *data = transport->data;
295 int i;
296 struct ref *posn;
297 struct strbuf buf = STRBUF_INIT;
298
299 + get_helper(transport);
300 +
301 if (get_importer(transport, &fastimport))
302 die("Couldn't run fast-import");
303
@@ -264,7 +307,7 @@ static int fetch_with_import(struct transport *transport,
307 continue;
308
309 strbuf_addf(&buf, "import %s\n", posn->name);
267 - write_in_full(helper->in, buf.buf, buf.len);
310 + sendline(data, &buf);
311 strbuf_reset(&buf);
312 }
313 disconnect_helper(transport);
@@ -369,17 +412,14 @@ static int push_refs(struct transport *transport,
412 }
413
414 strbuf_addch(&buf, '\n');
372 - if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
373 - exit(128);
415 + sendline(data, &buf);
416
417 ref = remote_refs;
418 while (1) {
419 char *refname, *msg;
420 int status;
421
380 - strbuf_reset(&buf);
381 - if (strbuf_getline(&buf, data->out, '\n') == EOF)
382 - exit(128); /* child died, message supplied already */
422 + recvline(data, &buf);
423 if (!buf.len)
424 break;
425
@@ -471,8 +511,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
511
512 while (1) {
513 char *eov, *eon;
474 - if (strbuf_getline(&buf, data->out, '\n') == EOF)
475 - exit(128); /* child died, message supplied already */
514 + recvline(data, &buf);
515
516 if (!*buf.buf)
517 break;
@@ -497,6 +536,8 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
536 }
537 tail = &((*tail)->next);
538 }
539 + if (debug)
540 + fprintf(stderr, "Debug: Read ref listing.\n");
541 strbuf_release(&buf);
542
543 for (posn = ret; posn; posn = posn->next)
@@ -510,6 +551,9 @@ int transport_helper_init(struct transport *transport, const char *name)
551 struct helper_data *data = xcalloc(sizeof(*data), 1);
552 data->name = name;
553
554 + if (getenv("GIT_TRANSPORT_HELPER_DEBUG"))
555 + debug = 1;
556 +
557 transport->data = data;
558 transport->set_option = set_helper_option;
559 transport->get_refs_list = get_refs_list;