Skip to content

Commit

Permalink
Add remote helper debug mode
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ilari Liusvaara authored and Junio C Hamano committed Dec 9, 2009
1 parent a24a32d commit bf3c523
Showing 1 changed file with 69 additions and 25 deletions.
94 changes: 69 additions & 25 deletions transport-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "quote.h"
#include "remote.h"

static int debug;

struct helper_data
{
const char *name;
Expand All @@ -22,6 +24,45 @@ struct helper_data
int refspec_nr;
};

static void sendline(struct helper_data *helper, struct strbuf *buffer)
{
if (debug)
fprintf(stderr, "Debug: Remote helper: -> %s", buffer->buf);
if (write_in_full(helper->helper->in, buffer->buf, buffer->len)
!= buffer->len)
die_errno("Full write to remote helper failed");
}

static int recvline(struct helper_data *helper, struct strbuf *buffer)
{
strbuf_reset(buffer);
if (debug)
fprintf(stderr, "Debug: Remote helper: Waiting...\n");
if (strbuf_getline(buffer, helper->out, '\n') == EOF) {
if (debug)
fprintf(stderr, "Debug: Remote helper quit.\n");
exit(128);
}

if (debug)
fprintf(stderr, "Debug: Remote helper: <- %s\n", buffer->buf);
return 0;
}

static void xchgline(struct helper_data *helper, struct strbuf *buffer)
{
sendline(helper, buffer);
recvline(helper, buffer);
}

static void write_constant(int fd, const char *str)
{
if (debug)
fprintf(stderr, "Debug: Remote helper: -> %s", str);
if (write_in_full(fd, str, strlen(str)) != strlen(str))
die_errno("Full write to remote helper failed");
}

static struct child_process *get_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
Expand All @@ -48,15 +89,16 @@ static struct child_process *get_helper(struct transport *transport)
die("Unable to run helper: git %s", helper->argv[0]);
data->helper = helper;

write_str_in_full(helper->in, "capabilities\n");
write_constant(helper->in, "capabilities\n");

data->out = xfdopen(helper->out, "r");
while (1) {
if (strbuf_getline(&buf, data->out, '\n') == EOF)
exit(128); /* child died, message supplied already */
recvline(data, &buf);

if (!*buf.buf)
break;
if (debug)
fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
if (!strcmp(buf.buf, "fetch"))
data->fetch = 1;
if (!strcmp(buf.buf, "option"))
Expand All @@ -82,14 +124,21 @@ static struct child_process *get_helper(struct transport *transport)
free(refspecs);
}
strbuf_release(&buf);
if (debug)
fprintf(stderr, "Debug: Capabilities complete.\n");
return data->helper;
}

static int disconnect_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
struct strbuf buf = STRBUF_INIT;

if (data->helper) {
write_str_in_full(data->helper->in, "\n");
if (debug)
fprintf(stderr, "Debug: Disconnecting.\n");
strbuf_addf(&buf, "\n");
sendline(data, &buf);
close(data->helper->in);
fclose(data->out);
finish_command(data->helper);
Expand Down Expand Up @@ -117,10 +166,11 @@ static int set_helper_option(struct transport *transport,
const char *name, const char *value)
{
struct helper_data *data = transport->data;
struct child_process *helper = get_helper(transport);
struct strbuf buf = STRBUF_INIT;
int i, ret, is_bool = 0;

get_helper(transport);

if (!data->option)
return 1;

Expand All @@ -143,12 +193,7 @@ static int set_helper_option(struct transport *transport,
quote_c_style(value, &buf, NULL, 0);
strbuf_addch(&buf, '\n');

if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
die_errno("cannot send option to %s", data->name);

strbuf_reset(&buf);
if (strbuf_getline(&buf, data->out, '\n') == EOF)
exit(128); /* child died, message supplied already */
xchgline(data, &buf);

if (!strcmp(buf.buf, "ok"))
ret = 0;
Expand Down Expand Up @@ -208,13 +253,10 @@ static int fetch_with_fetch(struct transport *transport,
}

strbuf_addch(&buf, '\n');
if (write_in_full(data->helper->in, buf.buf, buf.len) != buf.len)
die_errno("cannot send fetch to %s", data->name);
sendline(data, &buf);

while (1) {
strbuf_reset(&buf);
if (strbuf_getline(&buf, data->out, '\n') == EOF)
exit(128); /* child died, message supplied already */
recvline(data, &buf);

if (!prefixcmp(buf.buf, "lock ")) {
const char *name = buf.buf + 5;
Expand Down Expand Up @@ -249,12 +291,13 @@ static int fetch_with_import(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
struct child_process fastimport;
struct child_process *helper = get_helper(transport);
struct helper_data *data = transport->data;
int i;
struct ref *posn;
struct strbuf buf = STRBUF_INIT;

get_helper(transport);

if (get_importer(transport, &fastimport))
die("Couldn't run fast-import");

Expand All @@ -264,7 +307,7 @@ static int fetch_with_import(struct transport *transport,
continue;

strbuf_addf(&buf, "import %s\n", posn->name);
write_in_full(helper->in, buf.buf, buf.len);
sendline(data, &buf);
strbuf_reset(&buf);
}
disconnect_helper(transport);
Expand Down Expand Up @@ -369,17 +412,14 @@ static int push_refs(struct transport *transport,
}

strbuf_addch(&buf, '\n');
if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
exit(128);
sendline(data, &buf);

ref = remote_refs;
while (1) {
char *refname, *msg;
int status;

strbuf_reset(&buf);
if (strbuf_getline(&buf, data->out, '\n') == EOF)
exit(128); /* child died, message supplied already */
recvline(data, &buf);
if (!buf.len)
break;

Expand Down Expand Up @@ -471,8 +511,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)

while (1) {
char *eov, *eon;
if (strbuf_getline(&buf, data->out, '\n') == EOF)
exit(128); /* child died, message supplied already */
recvline(data, &buf);

if (!*buf.buf)
break;
Expand All @@ -497,6 +536,8 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
}
tail = &((*tail)->next);
}
if (debug)
fprintf(stderr, "Debug: Read ref listing.\n");
strbuf_release(&buf);

for (posn = ret; posn; posn = posn->next)
Expand All @@ -510,6 +551,9 @@ int transport_helper_init(struct transport *transport, const char *name)
struct helper_data *data = xcalloc(sizeof(*data), 1);
data->name = name;

if (getenv("GIT_TRANSPORT_HELPER_DEBUG"))
debug = 1;

transport->data = data;
transport->set_option = set_helper_option;
transport->get_refs_list = get_refs_list;
Expand Down

0 comments on commit bf3c523

Please sign in to comment.