diff options
Diffstat (limited to 'builtin/receive-pack.c')
-rw-r--r-- | builtin/receive-pack.c | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index bb9909c52e..f1f0f7bef6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -977,15 +977,25 @@ static int read_proc_receive_report(struct packet_reader *reader, int new_report = 0; int code = 0; int once = 0; + int response = 0; for (;;) { struct object_id old_oid, new_oid; const char *head; const char *refname; char *p; - - if (packet_reader_read(reader) != PACKET_READ_NORMAL) + enum packet_read_status status; + + status = packet_reader_read(reader); + if (status != PACKET_READ_NORMAL) { + /* Check whether proc-receive exited abnormally */ + if (status == PACKET_READ_EOF && !response) { + strbuf_addstr(errmsg, "proc-receive exited abnormally"); + return -1; + } break; + } + response++; head = reader->line; p = strchr(head, ' '); @@ -1145,31 +1155,49 @@ static int run_proc_receive_hook(struct command *commands, if (use_push_options) strbuf_addstr(&cap, " push-options"); if (cap.len) { - packet_write_fmt(proc.in, "version=1%c%s\n", '\0', cap.buf + 1); + code = packet_write_fmt_gently(proc.in, "version=1%c%s\n", '\0', cap.buf + 1); strbuf_release(&cap); } else { - packet_write_fmt(proc.in, "version=1\n"); + code = packet_write_fmt_gently(proc.in, "version=1\n"); } - packet_flush(proc.in); + if (!code) + code = packet_flush_gently(proc.in); - for (;;) { - int linelen; + if (!code) + for (;;) { + int linelen; + enum packet_read_status status; - if (packet_reader_read(&reader) != PACKET_READ_NORMAL) - break; + status = packet_reader_read(&reader); + if (status != PACKET_READ_NORMAL) { + /* Check whether proc-receive exited abnormally */ + if (status == PACKET_READ_EOF) + code = -1; + break; + } - if (reader.pktlen > 8 && starts_with(reader.line, "version=")) { - version = atoi(reader.line + 8); - linelen = strlen(reader.line); - if (linelen < reader.pktlen) { - const char *feature_list = reader.line + linelen + 1; - if (parse_feature_request(feature_list, "push-options")) - hook_use_push_options = 1; + if (reader.pktlen > 8 && starts_with(reader.line, "version=")) { + version = atoi(reader.line + 8); + linelen = strlen(reader.line); + if (linelen < reader.pktlen) { + const char *feature_list = reader.line + linelen + 1; + if (parse_feature_request(feature_list, "push-options")) + hook_use_push_options = 1; + } } } + + if (code) { + strbuf_addstr(&errmsg, "fail to negotiate version with proc-receive hook"); + goto cleanup; } - if (version != 1) { + switch (version) { + case 0: + /* fallthrough */ + case 1: + break; + default: strbuf_addf(&errmsg, "proc-receive version '%d' is not supported", version); code = -1; @@ -1180,20 +1208,36 @@ static int run_proc_receive_hook(struct command *commands, for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->run_proc_receive || cmd->skip_update || cmd->error_string) continue; - packet_write_fmt(proc.in, "%s %s %s", - oid_to_hex(&cmd->old_oid), - oid_to_hex(&cmd->new_oid), - cmd->ref_name); + code = packet_write_fmt_gently(proc.in, "%s %s %s", + oid_to_hex(&cmd->old_oid), + oid_to_hex(&cmd->new_oid), + cmd->ref_name); + if (code) + break; + } + if (!code) + code = packet_flush_gently(proc.in); + if (code) { + strbuf_addstr(&errmsg, "fail to write commands to proc-receive hook"); + goto cleanup; } - packet_flush(proc.in); /* Send push options */ if (hook_use_push_options) { struct string_list_item *item; - for_each_string_list_item(item, push_options) - packet_write_fmt(proc.in, "%s", item->string); - packet_flush(proc.in); + for_each_string_list_item(item, push_options) { + code = packet_write_fmt_gently(proc.in, "%s", item->string); + if (code) + break; + } + if (!code) + code = packet_flush_gently(proc.in); + if (code) { + strbuf_addstr(&errmsg, + "fail to write push-options to proc-receive hook"); + goto cleanup; + } } /* Read result from proc-receive */ |