send-pack: demultiplex a sideband stream with status data · msysgit/git@0c499ea
@@ -372,6 +372,14 @@ static void print_helper_status(struct ref *ref)
372372strbuf_release(&buf);
373373}
374374375+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+375383int send_pack(struct send_pack_args *args,
376384int fd[], struct child_process *conn,
377385struct ref *remote_refs,
@@ -382,18 +390,22 @@ int send_pack(struct send_pack_args *args,
382390struct strbuf req_buf = STRBUF_INIT;
383391struct ref *ref;
384392int new_refs;
385-int ask_for_status_report = 0;
386393int 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;
388397int ret;
398+struct async demux;
389399390400/* Does the other end support the reporting? */
391401if (server_supports("report-status"))
392-ask_for_status_report = 1;
402+status_report = 1;
393403if (server_supports("delete-refs"))
394404allow_deleting_refs = 1;
395405if (server_supports("ofs-delta"))
396406args->use_ofs_delta = 1;
407+if (server_supports("side-band-64k"))
408+use_sideband = 1;
397409398410if (!remote_refs) {
399411fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@@ -456,28 +468,30 @@ int send_pack(struct send_pack_args *args,
456468if (!ref->deletion)
457469new_refs++;
458470459-if (!args->dry_run) {
471+if (args->dry_run) {
472+ref->status = REF_STATUS_OK;
473+ } else {
460474char *old_hex = sha1_to_hex(ref->old_sha1);
461475char *new_hex = sha1_to_hex(ref->new_sha1);
462476463-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",
465479old_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" : "");
469482 }
470483else
471484packet_buf_write(&req_buf, "%s %s %s",
472485old_hex, new_hex, ref->name);
486+ref->status = status_report ?
487+REF_STATUS_EXPECTING_REPORT :
488+REF_STATUS_OK;
489+cmds_sent++;
473490 }
474-ref->status = expect_status_report ?
475-REF_STATUS_EXPECTING_REPORT :
476-REF_STATUS_OK;
477491 }
478492479493if (args->stateless_rpc) {
480-if (!args->dry_run) {
494+if (!args->dry_run && cmds_sent) {
481495packet_buf_flush(&req_buf);
482496send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
483497 }
@@ -487,23 +501,43 @@ int send_pack(struct send_pack_args *args,
487501 }
488502strbuf_release(&req_buf);
489503490-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) {
491515if (pack_objects(out, remote_refs, extra_have, args) < 0) {
492516for (ref = remote_refs; ref; ref = ref->next)
493517ref->status = REF_STATUS_NONE;
518+if (use_sideband)
519+finish_async(&demux);
494520return -1;
495521 }
496522 }
497-if (args->stateless_rpc && !args->dry_run)
523+if (args->stateless_rpc && cmds_sent)
498524packet_flush(out);
499525500-if (expect_status_report)
526+if (status_report && cmds_sent)
501527ret = receive_status(in, remote_refs);
502528else
503529ret = 0;
504530if (args->stateless_rpc)
505531packet_flush(out);
506532533+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+507541if (ret < 0)
508542return ret;
509543for (ref = remote_refs; ref; ref = ref->next) {