@@ -38,6 +38,7 @@ static struct lock_file shallow_lock;
3838static const char * alternate_shallow_file ;
3939static char * negotiation_algorithm ;
4040static struct strbuf fsck_msg_types = STRBUF_INIT ;
41+ static struct string_list uri_protocols = STRING_LIST_INIT_DUP ;
4142
4243/* Remember to update object flag allocation in object.h */
4344#define COMPLETE (1U << 0)
@@ -755,7 +756,8 @@ static int sideband_demux(int in, int out, void *data)
755756}
756757
757758static int get_pack (struct fetch_pack_args * args ,
758- int xd [2 ], struct string_list * pack_lockfiles )
759+ int xd [2 ], struct string_list * pack_lockfiles ,
760+ int only_packfile )
759761{
760762 struct async demux ;
761763 int do_keep = args -> keep_pack ;
@@ -815,8 +817,15 @@ static int get_pack(struct fetch_pack_args *args,
815817 "--keep=fetch-pack %" PRIuMAX " on %s" ,
816818 (uintmax_t )getpid (), hostname );
817819 }
818- if (args -> check_self_contained_and_connected )
820+ if (only_packfile && args -> check_self_contained_and_connected )
819821 argv_array_push (& cmd .args , "--check-self-contained-and-connected" );
822+ else
823+ /*
824+ * We cannot perform any connectivity checks because
825+ * not all packs have been downloaded; let the caller
826+ * have this responsibility.
827+ */
828+ args -> check_self_contained_and_connected = 0 ;
820829 if (args -> from_promisor )
821830 argv_array_push (& cmd .args , "--promisor" );
822831 }
@@ -993,7 +1002,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
9931002 alternate_shallow_file = setup_temporary_shallow (si -> shallow );
9941003 else
9951004 alternate_shallow_file = NULL ;
996- if (get_pack (args , fd , pack_lockfiles ))
1005+ if (get_pack (args , fd , pack_lockfiles , 1 ))
9971006 die (_ ("git fetch-pack: fetch failed." ));
9981007
9991008 all_done :
@@ -1148,6 +1157,26 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
11481157 warning ("filtering not recognized by server, ignoring" );
11491158 }
11501159
1160+ if (server_supports_feature ("fetch" , "packfile-uris" , 0 )) {
1161+ int i ;
1162+ struct strbuf to_send = STRBUF_INIT ;
1163+
1164+ for (i = 0 ; i < uri_protocols .nr ; i ++ ) {
1165+ const char * s = uri_protocols .items [i ].string ;
1166+
1167+ if (!strcmp (s , "https" ) || !strcmp (s , "http" )) {
1168+ if (to_send .len )
1169+ strbuf_addch (& to_send , ',' );
1170+ strbuf_addstr (& to_send , s );
1171+ }
1172+ }
1173+ if (to_send .len ) {
1174+ packet_buf_write (& req_buf , "packfile-uris %s" ,
1175+ to_send .buf );
1176+ strbuf_release (& to_send );
1177+ }
1178+ }
1179+
11511180 /* add wants */
11521181 add_wants (args -> no_dependents , wants , & req_buf );
11531182
@@ -1323,6 +1352,21 @@ static void receive_wanted_refs(struct packet_reader *reader,
13231352 die (_ ("error processing wanted refs: %d" ), reader -> status );
13241353}
13251354
1355+ static void receive_packfile_uris (struct packet_reader * reader ,
1356+ struct string_list * uris )
1357+ {
1358+ process_section_header (reader , "packfile-uris" , 0 );
1359+ while (packet_reader_read (reader ) == PACKET_READ_NORMAL ) {
1360+ if (reader -> pktlen < the_hash_algo -> hexsz ||
1361+ reader -> line [the_hash_algo -> hexsz ] != ' ' )
1362+ die ("expected '<hash> <uri>', got: %s\n" , reader -> line );
1363+
1364+ string_list_append (uris , reader -> line );
1365+ }
1366+ if (reader -> status != PACKET_READ_DELIM )
1367+ die ("expected DELIM" );
1368+ }
1369+
13261370enum fetch_state {
13271371 FETCH_CHECK_LOCAL = 0 ,
13281372 FETCH_SEND_REQUEST ,
@@ -1344,6 +1388,9 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
13441388 int in_vain = 0 ;
13451389 int haves_to_send = INITIAL_FLUSH ;
13461390 struct fetch_negotiator negotiator ;
1391+ struct string_list packfile_uris = STRING_LIST_INIT_DUP ;
1392+ int i ;
1393+
13471394 fetch_negotiator_init (& negotiator , negotiation_algorithm );
13481395 packet_reader_init (& reader , fd [0 ], NULL , 0 ,
13491396 PACKET_READ_CHOMP_NEWLINE |
@@ -1414,9 +1461,12 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
14141461 if (process_section_header (& reader , "wanted-refs" , 1 ))
14151462 receive_wanted_refs (& reader , sought , nr_sought );
14161463
1417- /* get the pack */
1464+ /* get the pack(s) */
1465+ if (process_section_header (& reader , "packfile-uris" , 1 ))
1466+ receive_packfile_uris (& reader , & packfile_uris );
14181467 process_section_header (& reader , "packfile" , 0 );
1419- if (get_pack (args , fd , pack_lockfiles ))
1468+ if (get_pack (args , fd , pack_lockfiles ,
1469+ !packfile_uris .nr ))
14201470 die (_ ("git fetch-pack: fetch failed." ));
14211471
14221472 state = FETCH_DONE ;
@@ -1426,6 +1476,50 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
14261476 }
14271477 }
14281478
1479+ for (i = 0 ; i < packfile_uris .nr ; i ++ ) {
1480+ struct child_process cmd = CHILD_PROCESS_INIT ;
1481+ char packname [GIT_MAX_HEXSZ + 1 ];
1482+ const char * uri = packfile_uris .items [i ].string +
1483+ the_hash_algo -> hexsz + 1 ;
1484+
1485+ argv_array_push (& cmd .args , "http-fetch" );
1486+ argv_array_push (& cmd .args , "--packfile" );
1487+ argv_array_push (& cmd .args , uri );
1488+ cmd .git_cmd = 1 ;
1489+ cmd .no_stdin = 1 ;
1490+ cmd .out = -1 ;
1491+ if (start_command (& cmd ))
1492+ die ("fetch-pack: unable to spawn http-fetch" );
1493+
1494+ if (read_in_full (cmd .out , packname , 5 ) < 0 ||
1495+ memcmp (packname , "keep\t" , 5 ))
1496+ die ("fetch-pack: expected keep then TAB at start of http-fetch output" );
1497+
1498+ if (read_in_full (cmd .out , packname ,
1499+ the_hash_algo -> hexsz + 1 ) < 0 ||
1500+ packname [the_hash_algo -> hexsz ] != '\n' )
1501+ die ("fetch-pack: expected hash then LF at end of http-fetch output" );
1502+
1503+ packname [the_hash_algo -> hexsz ] = '\0' ;
1504+
1505+ close (cmd .out );
1506+
1507+ if (finish_command (& cmd ))
1508+ die ("fetch-pack: unable to finish http-fetch" );
1509+
1510+ if (memcmp (packfile_uris .items [i ].string , packname ,
1511+ the_hash_algo -> hexsz ))
1512+ die ("fetch-pack: pack downloaded from %s does not match expected hash %.*s" ,
1513+ uri , (int ) the_hash_algo -> hexsz ,
1514+ packfile_uris .items [i ].string );
1515+
1516+ string_list_append_nodup (pack_lockfiles ,
1517+ xstrfmt ("%s/pack/pack-%s.keep" ,
1518+ get_object_directory (),
1519+ packname ));
1520+ }
1521+ string_list_clear (& packfile_uris , 0 );
1522+
14291523 negotiator .release (& negotiator );
14301524 oidset_clear (& common );
14311525 return ref ;
@@ -1465,6 +1559,14 @@ static void fetch_pack_config(void)
14651559 git_config_get_bool ("transfer.fsckobjects" , & transfer_fsck_objects );
14661560 git_config_get_string ("fetch.negotiationalgorithm" ,
14671561 & negotiation_algorithm );
1562+ if (!uri_protocols .nr ) {
1563+ char * str ;
1564+
1565+ if (!git_config_get_string ("fetch.uriprotocols" , & str ) && str ) {
1566+ string_list_split (& uri_protocols , str , ',' , -1 );
1567+ free (str );
1568+ }
1569+ }
14681570
14691571 git_config (fetch_pack_config_cb , NULL );
14701572}
0 commit comments