From 185c04e041fb33191c5828339381fd8c4058a43a Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 5 Feb 2010 12:57:40 -0800 Subject: receive-pack: Refactor how capabilities are shown to the client Moving capability advertisement into the packet_write call itself makes it easier to add additional capabilities to the list, be it optional by configuration, or always present in the protocol. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-receive-pack.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'builtin-receive-pack.c') diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c index 78c0e69cdc..325ec6e2c4 100644 --- a/builtin-receive-pack.c +++ b/builtin-receive-pack.c @@ -31,7 +31,7 @@ static int prefer_ofs_delta = 1; static int auto_update_server_info; static int auto_gc = 1; static const char *head_name; -static char *capabilities_to_send; +static int sent_capabilities; static enum deny_action parse_deny_action(const char *var, const char *value) { @@ -105,19 +105,21 @@ static int receive_pack_config(const char *var, const char *value, void *cb) static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { - if (!capabilities_to_send) + if (sent_capabilities) packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); else - packet_write(1, "%s %s%c%s\n", - sha1_to_hex(sha1), path, 0, capabilities_to_send); - capabilities_to_send = NULL; + packet_write(1, "%s %s%c%s%s\n", + sha1_to_hex(sha1), path, 0, + " report-status delete-refs", + prefer_ofs_delta ? " ofs-delta" : ""); + sent_capabilities = 1; return 0; } static void write_head_info(void) { for_each_ref(show_ref, NULL); - if (capabilities_to_send) + if (!sent_capabilities) show_ref("capabilities^{}", null_sha1, 0, NULL); } @@ -670,10 +672,6 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) else if (0 <= receive_unpack_limit) unpack_limit = receive_unpack_limit; - capabilities_to_send = (prefer_ofs_delta) ? - " report-status delete-refs ofs-delta " : - " report-status delete-refs "; - if (advertise_refs || !stateless_rpc) { add_alternate_refs(); write_head_info(); -- cgit v1.2.1 From 38a81b4e82ebf57549f2fa082b329c36dffc0b18 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 5 Feb 2010 12:57:41 -0800 Subject: receive-pack: Wrap status reports inside side-band-64k If the client requests the side-band-64k protocol capability we now wrap the status report data inside of packets sent to band #1. This permits us to later send additional progress or informational messages down band #2. If side-band-64k was enabled, we always send a final flush packet to let the client know we are done transmitting. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-receive-pack.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'builtin-receive-pack.c') diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c index 325ec6e2c4..ff3f11731d 100644 --- a/builtin-receive-pack.c +++ b/builtin-receive-pack.c @@ -2,6 +2,7 @@ #include "pack.h" #include "refs.h" #include "pkt-line.h" +#include "sideband.h" #include "run-command.h" #include "exec_cmd.h" #include "commit.h" @@ -27,6 +28,7 @@ static int receive_unpack_limit = -1; static int transfer_unpack_limit = -1; static int unpack_limit = 100; static int report_status; +static int use_sideband; static int prefer_ofs_delta = 1; static int auto_update_server_info; static int auto_gc = 1; @@ -110,7 +112,7 @@ static int show_ref(const char *path, const unsigned char *sha1, int flag, void else packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), path, 0, - " report-status delete-refs", + " report-status delete-refs side-band-64k", prefer_ofs_delta ? " ofs-delta" : ""); sent_capabilities = 1; return 0; @@ -466,6 +468,8 @@ static void read_head_info(void) if (reflen + 82 < len) { if (strstr(refname + reflen + 1, "report-status")) report_status = 1; + if (strstr(refname + reflen + 1, "side-band-64k")) + use_sideband = LARGE_PACKET_MAX; } cmd = xmalloc(sizeof(struct command) + len - 80); hashcpy(cmd->old_sha1, old_sha1); @@ -565,17 +569,25 @@ static const char *unpack(void) static void report(const char *unpack_status) { struct command *cmd; - packet_write(1, "unpack %s\n", - unpack_status ? unpack_status : "ok"); + struct strbuf buf = STRBUF_INIT; + + packet_buf_write(&buf, "unpack %s\n", + unpack_status ? unpack_status : "ok"); for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) - packet_write(1, "ok %s\n", - cmd->ref_name); + packet_buf_write(&buf, "ok %s\n", + cmd->ref_name); else - packet_write(1, "ng %s %s\n", - cmd->ref_name, cmd->error_string); + packet_buf_write(&buf, "ng %s %s\n", + cmd->ref_name, cmd->error_string); } - packet_flush(1); + packet_buf_flush(&buf); + + if (use_sideband) + send_sideband(1, 1, buf.buf, buf.len, use_sideband); + else + safe_write(1, buf.buf, buf.len); + strbuf_release(&buf); } static int delete_only(struct command *cmd) @@ -705,5 +717,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) if (auto_update_server_info) update_server_info(0); } + if (use_sideband) + packet_flush(1); return 0; } -- cgit v1.2.1 From 6d525d389fbef814b11e41f196e6656f2e95f412 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 5 Feb 2010 12:57:42 -0800 Subject: receive-pack: Send hook output over side band #2 If the client requests to enable side-band-64k capability we can safely send any hook stdout or stderr data down side band #2, so the client can present it to the user. If side-band-64k isn't enabled, hooks continue to inherit stderr from the parent receive-pack process. When the side band channel is being used the push client will wind up prefixing all server messages with "remote: ", just like fetch does, so our test vector has to be updated with the new expected output. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-receive-pack.c | 65 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) (limited to 'builtin-receive-pack.c') diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c index ff3f11731d..da1c26b6be 100644 --- a/builtin-receive-pack.c +++ b/builtin-receive-pack.c @@ -139,11 +139,25 @@ static struct command *commands; static const char pre_receive_hook[] = "hooks/pre-receive"; static const char post_receive_hook[] = "hooks/post-receive"; +static int copy_to_sideband(int in, int out, void *arg) +{ + char data[128]; + while (1) { + ssize_t sz = xread(in, data, sizeof(data)); + if (sz <= 0) + break; + send_sideband(1, 2, data, sz, use_sideband); + } + close(in); + return 0; +} + static int run_receive_hook(const char *hook_name) { static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4]; struct command *cmd; struct child_process proc; + struct async muxer; const char *argv[2]; int have_input = 0, code; @@ -163,9 +177,23 @@ static int run_receive_hook(const char *hook_name) proc.in = -1; proc.stdout_to_stderr = 1; + if (use_sideband) { + memset(&muxer, 0, sizeof(muxer)); + muxer.proc = copy_to_sideband; + muxer.in = -1; + code = start_async(&muxer); + if (code) + return code; + proc.err = muxer.in; + } + code = start_command(&proc); - if (code) + if (code) { + if (use_sideband) + finish_async(&muxer); return code; + } + for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) { size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n", @@ -177,6 +205,8 @@ static int run_receive_hook(const char *hook_name) } } close(proc.in); + if (use_sideband) + finish_async(&muxer); return finish_command(&proc); } @@ -184,6 +214,8 @@ static int run_update_hook(struct command *cmd) { static const char update_hook[] = "hooks/update"; const char *argv[5]; + struct child_process proc; + int code; if (access(update_hook, X_OK) < 0) return 0; @@ -194,8 +226,18 @@ static int run_update_hook(struct command *cmd) argv[3] = sha1_to_hex(cmd->new_sha1); argv[4] = NULL; - return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | - RUN_COMMAND_STDOUT_TO_STDERR); + memset(&proc, 0, sizeof(proc)); + proc.no_stdin = 1; + proc.stdout_to_stderr = 1; + proc.err = use_sideband ? -1 : 0; + proc.argv = argv; + + code = start_command(&proc); + if (code) + return code; + if (use_sideband) + copy_to_sideband(proc.err, -1, NULL); + return finish_command(&proc); } static int is_ref_checked_out(const char *ref) @@ -384,8 +426,9 @@ static char update_post_hook[] = "hooks/post-update"; static void run_update_post_hook(struct command *cmd) { struct command *cmd_p; - int argc, status; + int argc; const char **argv; + struct child_process proc; for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) { if (cmd_p->error_string) @@ -407,8 +450,18 @@ static void run_update_post_hook(struct command *cmd) argc++; } argv[argc] = NULL; - status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN - | RUN_COMMAND_STDOUT_TO_STDERR); + + memset(&proc, 0, sizeof(proc)); + proc.no_stdin = 1; + proc.stdout_to_stderr = 1; + proc.err = use_sideband ? -1 : 0; + proc.argv = argv; + + if (!start_command(&proc)) { + if (use_sideband) + copy_to_sideband(proc.err, -1, NULL); + finish_command(&proc); + } } static void execute_commands(const char *unpacker_error) -- cgit v1.2.1