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;