@@ -398,6 +398,7 @@ struct git_transport_data {
398
398
struct git_transport_options options ;
399
399
struct child_process * conn ;
400
400
int fd [2 ];
401
+ unsigned got_remote_heads : 1 ;
401
402
struct extra_have_objects extra_have ;
402
403
};
403
404
@@ -432,10 +433,15 @@ static int set_git_option(struct git_transport_options *opts,
432
433
static int connect_setup (struct transport * transport , int for_push , int verbose )
433
434
{
434
435
struct git_transport_data * data = transport -> data ;
436
+
437
+ if (data -> conn )
438
+ return 0 ;
439
+
435
440
data -> conn = git_connect (data -> fd , transport -> url ,
436
441
for_push ? data -> options .receivepack :
437
442
data -> options .uploadpack ,
438
443
verbose ? CONNECT_VERBOSE : 0 );
444
+
439
445
return 0 ;
440
446
}
441
447
@@ -447,6 +453,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
447
453
connect_setup (transport , for_push , 0 );
448
454
get_remote_heads (data -> fd [0 ], & refs , 0 , NULL ,
449
455
for_push ? REF_NORMAL : 0 , & data -> extra_have );
456
+ data -> got_remote_heads = 1 ;
450
457
451
458
return refs ;
452
459
}
@@ -477,9 +484,10 @@ static int fetch_refs_via_pack(struct transport *transport,
477
484
for (i = 0 ; i < nr_heads ; i ++ )
478
485
origh [i ] = heads [i ] = xstrdup (to_fetch [i ]-> name );
479
486
480
- if (!data -> conn ) {
487
+ if (!data -> got_remote_heads ) {
481
488
connect_setup (transport , 0 , 0 );
482
489
get_remote_heads (data -> fd [0 ], & refs_tmp , 0 , NULL , 0 , NULL );
490
+ data -> got_remote_heads = 1 ;
483
491
}
484
492
485
493
refs = fetch_pack (& args , data -> fd , data -> conn ,
@@ -490,6 +498,7 @@ static int fetch_refs_via_pack(struct transport *transport,
490
498
if (finish_connect (data -> conn ))
491
499
refs = NULL ;
492
500
data -> conn = NULL ;
501
+ data -> got_remote_heads = 0 ;
493
502
494
503
free_refs (refs_tmp );
495
504
@@ -718,12 +727,13 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
718
727
struct send_pack_args args ;
719
728
int ret ;
720
729
721
- if (!data -> conn ) {
730
+ if (!data -> got_remote_heads ) {
722
731
struct ref * tmp_refs ;
723
732
connect_setup (transport , 1 , 0 );
724
733
725
734
get_remote_heads (data -> fd [0 ], & tmp_refs , 0 , NULL , REF_NORMAL ,
726
735
NULL );
736
+ data -> got_remote_heads = 1 ;
727
737
}
728
738
729
739
memset (& args , 0 , sizeof (args ));
@@ -741,6 +751,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
741
751
close (data -> fd [0 ]);
742
752
ret |= finish_connect (data -> conn );
743
753
data -> conn = NULL ;
754
+ data -> got_remote_heads = 0 ;
744
755
745
756
return ret ;
746
757
}
@@ -749,7 +760,8 @@ static int disconnect_git(struct transport *transport)
749
760
{
750
761
struct git_transport_data * data = transport -> data ;
751
762
if (data -> conn ) {
752
- packet_flush (data -> fd [1 ]);
763
+ if (data -> got_remote_heads )
764
+ packet_flush (data -> fd [1 ]);
753
765
close (data -> fd [0 ]);
754
766
close (data -> fd [1 ]);
755
767
finish_connect (data -> conn );
@@ -759,6 +771,32 @@ static int disconnect_git(struct transport *transport)
759
771
return 0 ;
760
772
}
761
773
774
+ void transport_take_over (struct transport * transport ,
775
+ struct child_process * child )
776
+ {
777
+ struct git_transport_data * data ;
778
+
779
+ if (!transport -> smart_options )
780
+ die ("Bug detected: Taking over transport requires non-NULL "
781
+ "smart_options field." );
782
+
783
+ data = xcalloc (1 , sizeof (* data ));
784
+ data -> options = * transport -> smart_options ;
785
+ data -> conn = child ;
786
+ data -> fd [0 ] = data -> conn -> out ;
787
+ data -> fd [1 ] = data -> conn -> in ;
788
+ data -> got_remote_heads = 0 ;
789
+ transport -> data = data ;
790
+
791
+ transport -> set_option = NULL ;
792
+ transport -> get_refs_list = get_refs_via_connect ;
793
+ transport -> fetch = fetch_refs_via_pack ;
794
+ transport -> push = NULL ;
795
+ transport -> push_refs = git_transport_push ;
796
+ transport -> disconnect = disconnect_git ;
797
+ transport -> smart_options = & (data -> options );
798
+ }
799
+
762
800
static int is_local (const char * url )
763
801
{
764
802
const char * colon = strchr (url , ':' );
@@ -867,6 +905,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
867
905
ret -> smart_options = & (data -> options );
868
906
869
907
data -> conn = NULL ;
908
+ data -> got_remote_heads = 0 ;
870
909
} else if (!prefixcmp (url , "http://" )
871
910
|| !prefixcmp (url , "https://" )
872
911
|| !prefixcmp (url , "ftp://" )) {
@@ -927,9 +966,9 @@ int transport_push(struct transport *transport,
927
966
* nonfastforward = 0 ;
928
967
verify_remote_names (refspec_nr , refspec );
929
968
930
- if (transport -> push )
969
+ if (transport -> push ) {
931
970
return transport -> push (transport , refspec_nr , refspec , flags );
932
- if (transport -> push_refs ) {
971
+ } else if (transport -> push_refs ) {
933
972
struct ref * remote_refs =
934
973
transport -> get_refs_list (transport , 1 );
935
974
struct ref * local_refs = get_local_heads ();
@@ -973,6 +1012,7 @@ const struct ref *transport_get_remote_refs(struct transport *transport)
973
1012
{
974
1013
if (!transport -> remote_refs )
975
1014
transport -> remote_refs = transport -> get_refs_list (transport , 0 );
1015
+
976
1016
return transport -> remote_refs ;
977
1017
}
978
1018
@@ -1007,6 +1047,7 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
1007
1047
}
1008
1048
1009
1049
rc = transport -> fetch (transport , nr_heads , heads );
1050
+
1010
1051
free (heads );
1011
1052
return rc ;
1012
1053
}
0 commit comments