@@ -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+
375383int 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