Skip to content

Commit 0c499ea

Browse files
spearcegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ae6a560 commit 0c499ea

File tree

1 file changed

+50
-16
lines changed

1 file changed

+50
-16
lines changed

builtin-send-pack.c

+50-16
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,14 @@ static void print_helper_status(struct ref *ref)
372372
strbuf_release(&buf);
373373
}
374374

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+
375383
int send_pack(struct send_pack_args *args,
376384
int fd[], struct child_process *conn,
377385
struct ref *remote_refs,
@@ -382,18 +390,22 @@ int send_pack(struct send_pack_args *args,
382390
struct strbuf req_buf = STRBUF_INIT;
383391
struct ref *ref;
384392
int new_refs;
385-
int ask_for_status_report = 0;
386393
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;
388397
int ret;
398+
struct async demux;
389399

390400
/* Does the other end support the reporting? */
391401
if (server_supports("report-status"))
392-
ask_for_status_report = 1;
402+
status_report = 1;
393403
if (server_supports("delete-refs"))
394404
allow_deleting_refs = 1;
395405
if (server_supports("ofs-delta"))
396406
args->use_ofs_delta = 1;
407+
if (server_supports("side-band-64k"))
408+
use_sideband = 1;
397409

398410
if (!remote_refs) {
399411
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@@ -456,28 +468,30 @@ int send_pack(struct send_pack_args *args,
456468
if (!ref->deletion)
457469
new_refs++;
458470

459-
if (!args->dry_run) {
471+
if (args->dry_run) {
472+
ref->status = REF_STATUS_OK;
473+
} else {
460474
char *old_hex = sha1_to_hex(ref->old_sha1);
461475
char *new_hex = sha1_to_hex(ref->new_sha1);
462476

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",
465479
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" : "");
469482
}
470483
else
471484
packet_buf_write(&req_buf, "%s %s %s",
472485
old_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
}
478492

479493
if (args->stateless_rpc) {
480-
if (!args->dry_run) {
494+
if (!args->dry_run && cmds_sent) {
481495
packet_buf_flush(&req_buf);
482496
send_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
}
488502
strbuf_release(&req_buf);
489503

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) {
491515
if (pack_objects(out, remote_refs, extra_have, args) < 0) {
492516
for (ref = remote_refs; ref; ref = ref->next)
493517
ref->status = REF_STATUS_NONE;
518+
if (use_sideband)
519+
finish_async(&demux);
494520
return -1;
495521
}
496522
}
497-
if (args->stateless_rpc && !args->dry_run)
523+
if (args->stateless_rpc && cmds_sent)
498524
packet_flush(out);
499525

500-
if (expect_status_report)
526+
if (status_report && cmds_sent)
501527
ret = receive_status(in, remote_refs);
502528
else
503529
ret = 0;
504530
if (args->stateless_rpc)
505531
packet_flush(out);
506532

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+
507541
if (ret < 0)
508542
return ret;
509543
for (ref = remote_refs; ref; ref = ref->next) {

0 commit comments

Comments
 (0)