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

send-pack: demultiplex a sideband stream with status data

If the server advertises side-band-64k capability, we request it and pull the status report data out of side band #1, and let side band #2 go to our stderr. The latter channel be used by the remote side to send our user messages. This basically mirrors the side-band-64k capability in upload-pack. Servers may choose to use side band #2 to send error messages from hook scripts that are meant for the push end user. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Shawn O. Pearce committed Feb 5, 2010 at 12:57 UTC 0c499ea60fda716198c76f2d5febe3998d302afb
1 file changed +50 -16
builtin-send-pack.c
+50 -16
@@ -372,6 +372,14 @@ static void print_helper_status(struct ref *ref)
372 strbuf_release(&buf);
373 }
374
375 +static int sideband_demux(int in, int out, void *data)
376 +{
377 + int *fd = data;
378 + int ret = recv_sideband("send-pack", fd[0], out);
379 + close(out);
380 + return ret;
381 +}
382 +
383 int send_pack(struct send_pack_args *args,
384 int fd[], struct child_process *conn,
385 struct ref *remote_refs,
@@ -382,18 +390,22 @@ int send_pack(struct send_pack_args *args,
390 struct strbuf req_buf = STRBUF_INIT;
391 struct ref *ref;
392 int new_refs;
385 - int ask_for_status_report = 0;
393 int allow_deleting_refs = 0;
387 - int expect_status_report = 0;
394 + int status_report = 0;
395 + int use_sideband = 0;
396 + unsigned cmds_sent = 0;
397 int ret;
398 + struct async demux;
399
400 /* Does the other end support the reporting? */
401 if (server_supports("report-status"))
392 - ask_for_status_report = 1;
402 + status_report = 1;
403 if (server_supports("delete-refs"))
404 allow_deleting_refs = 1;
405 if (server_supports("ofs-delta"))
406 args->use_ofs_delta = 1;
407 + if (server_supports("side-band-64k"))
408 + use_sideband = 1;
409
410 if (!remote_refs) {
411 fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@@ -456,28 +468,30 @@ int send_pack(struct send_pack_args *args,
468 if (!ref->deletion)
469 new_refs++;
470
459 - if (!args->dry_run) {
471 + if (args->dry_run) {
472 + ref->status = REF_STATUS_OK;
473 + } else {
474 char *old_hex = sha1_to_hex(ref->old_sha1);
475 char *new_hex = sha1_to_hex(ref->new_sha1);
476
463 - if (ask_for_status_report) {
464 - packet_buf_write(&req_buf, "%s %s %s%c%s",
477 + if (!cmds_sent && (status_report || use_sideband)) {
478 + packet_buf_write(&req_buf, "%s %s %s%c%s%s",
479 old_hex, new_hex, ref->name, 0,
466 - "report-status");
467 - ask_for_status_report = 0;
468 - expect_status_report = 1;
480 + status_report ? " report-status" : "",
481 + use_sideband ? " side-band-64k" : "");
482 }
483 else
484 packet_buf_write(&req_buf, "%s %s %s",
485 old_hex, new_hex, ref->name);
486 + ref->status = status_report ?
487 + REF_STATUS_EXPECTING_REPORT :
488 + REF_STATUS_OK;
489 + cmds_sent++;
490 }
474 - ref->status = expect_status_report ?
475 - REF_STATUS_EXPECTING_REPORT :
476 - REF_STATUS_OK;
491 }
492
493 if (args->stateless_rpc) {
480 - if (!args->dry_run) {
494 + if (!args->dry_run && cmds_sent) {
495 packet_buf_flush(&req_buf);
496 send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
497 }
@@ -487,23 +501,43 @@ int send_pack(struct send_pack_args *args,
501 }
502 strbuf_release(&req_buf);
503
490 - if (new_refs && !args->dry_run) {
504 + if (use_sideband && cmds_sent) {
505 + memset(&demux, 0, sizeof(demux));
506 + demux.proc = sideband_demux;
507 + demux.data = fd;
508 + demux.out = -1;
509 + if (start_async(&demux))
510 + die("receive-pack: unable to fork off sideband demultiplexer");
511 + in = demux.out;
512 + }
513 +
514 + if (new_refs && cmds_sent) {
515 if (pack_objects(out, remote_refs, extra_have, args) < 0) {
516 for (ref = remote_refs; ref; ref = ref->next)
517 ref->status = REF_STATUS_NONE;
518 + if (use_sideband)
519 + finish_async(&demux);
520 return -1;
521 }
522 }
497 - if (args->stateless_rpc && !args->dry_run)
523 + if (args->stateless_rpc && cmds_sent)
524 packet_flush(out);
525
500 - if (expect_status_report)
526 + if (status_report && cmds_sent)
527 ret = receive_status(in, remote_refs);
528 else
529 ret = 0;
530 if (args->stateless_rpc)
531 packet_flush(out);
532
533 + if (use_sideband && cmds_sent) {
534 + if (finish_async(&demux)) {
535 + error("error in sideband demultiplexer");
536 + ret = -1;
537 + }
538 + close(demux.out);
539 + }
540 +
541 if (ret < 0)
542 return ret;
543 for (ref = remote_refs; ref; ref = ref->next) {