2525#include "oidset.h"
2626#include "packfile.h"
2727#include "odb.h"
28+ #include "object-name.h"
2829#include "path.h"
2930#include "connected.h"
3031#include "fetch-negotiator.h"
32+ #include "repo-settings.h"
3133#include "fsck.h"
3234#include "shallow.h"
3335#include "commit-reach.h"
@@ -332,6 +334,40 @@ static void send_filter(struct fetch_pack_args *args,
332334 }
333335}
334336
337+ static int add_oid_to_oidset (const struct reference * ref , void * cb_data )
338+ {
339+ struct oidset * set = cb_data ;
340+ oidset_insert (set , ref -> oid );
341+ return 0 ;
342+ }
343+
344+ static void resolve_have_refs (struct string_list * have_refs ,
345+ struct oidset * result )
346+ {
347+ struct string_list_item * item ;
348+
349+ if (!have_refs )
350+ return ;
351+
352+ for_each_string_list_item (item , have_refs ) {
353+ if (!has_glob_specials (item -> string )) {
354+ struct object_id oid ;
355+ if (repo_get_oid (the_repository , item -> string , & oid ))
356+ continue ;
357+ if (!odb_has_object (the_repository -> objects , & oid , 0 ))
358+ continue ;
359+ oidset_insert (result , & oid );
360+ } else {
361+ struct refs_for_each_ref_options opts = {
362+ .pattern = item -> string ,
363+ };
364+ refs_for_each_ref_ext (
365+ get_main_ref_store (the_repository ),
366+ add_oid_to_oidset , result , & opts );
367+ }
368+ }
369+ }
370+
335371static int find_common (struct fetch_negotiator * negotiator ,
336372 struct fetch_pack_args * args ,
337373 int fd [2 ], struct object_id * result_oid ,
@@ -347,6 +383,7 @@ static int find_common(struct fetch_negotiator *negotiator,
347383 struct strbuf req_buf = STRBUF_INIT ;
348384 size_t state_len = 0 ;
349385 struct packet_reader reader ;
386+ struct oidset have_refs_oids = OIDSET_INIT ;
350387
351388 if (args -> stateless_rpc && multi_ack == 1 )
352389 die (_ ("the option '%s' requires '%s'" ), "--stateless-rpc" , "multi_ack_detailed" );
@@ -474,7 +511,26 @@ static int find_common(struct fetch_negotiator *negotiator,
474511 trace2_region_enter ("fetch-pack" , "negotiation_v0_v1" , the_repository );
475512 flushes = 0 ;
476513 retval = -1 ;
514+
515+ /* Send unconditional haves from fetch.haveRefs */
516+ prepare_repo_settings (the_repository );
517+ resolve_have_refs (the_repository -> settings .fetch_have_refs ,
518+ & have_refs_oids );
519+ if (oidset_size (& have_refs_oids )) {
520+ struct oidset_iter iter ;
521+ oidset_iter_init (& have_refs_oids , & iter );
522+
523+ while ((oid = oidset_iter_next (& iter ))) {
524+ packet_buf_write (& req_buf , "have %s\n" ,
525+ oid_to_hex (oid ));
526+ print_verbose (args , "have %s" , oid_to_hex (oid ));
527+ }
528+ }
529+
477530 while ((oid = negotiator -> next (negotiator ))) {
531+ /* avoid duplicate oids as fetch.haveRefs. */
532+ if (oidset_contains (& have_refs_oids , oid ))
533+ continue ;
478534 packet_buf_write (& req_buf , "have %s\n" , oid_to_hex (oid ));
479535 print_verbose (args , "have %s" , oid_to_hex (oid ));
480536 in_vain ++ ;
@@ -584,6 +640,7 @@ static int find_common(struct fetch_negotiator *negotiator,
584640 flushes ++ ;
585641 }
586642 strbuf_release (& req_buf );
643+ oidset_clear (& have_refs_oids );
587644
588645 if (!got_ready || !no_done )
589646 consume_shallow_list (args , & reader );
@@ -1305,12 +1362,25 @@ static void add_common(struct strbuf *req_buf, struct oidset *common)
13051362
13061363static int add_haves (struct fetch_negotiator * negotiator ,
13071364 struct strbuf * req_buf ,
1308- int * haves_to_send )
1365+ int * haves_to_send ,
1366+ struct oidset * have_refs_oids )
13091367{
13101368 int haves_added = 0 ;
13111369 const struct object_id * oid ;
13121370
1371+ /* Send unconditional haves from fetch.haveRefs */
1372+ if (have_refs_oids ) {
1373+ struct oidset_iter iter ;
1374+ oidset_iter_init (have_refs_oids , & iter );
1375+
1376+ while ((oid = oidset_iter_next (& iter )))
1377+ packet_buf_write (req_buf , "have %s\n" ,
1378+ oid_to_hex (oid ));
1379+ }
1380+
13131381 while ((oid = negotiator -> next (negotiator ))) {
1382+ if (have_refs_oids && oidset_contains (have_refs_oids , oid ))
1383+ continue ;
13141384 packet_buf_write (req_buf , "have %s\n" , oid_to_hex (oid ));
13151385 if (++ haves_added >= * haves_to_send )
13161386 break ;
@@ -1358,7 +1428,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
13581428 struct fetch_pack_args * args ,
13591429 const struct ref * wants , struct oidset * common ,
13601430 int * haves_to_send , int * in_vain ,
1361- int sideband_all , int seen_ack )
1431+ int sideband_all , int seen_ack ,
1432+ struct oidset * have_refs_oids )
13621433{
13631434 int haves_added ;
13641435 int done_sent = 0 ;
@@ -1413,7 +1484,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
14131484 /* Add all of the common commits we've found in previous rounds */
14141485 add_common (& req_buf , common );
14151486
1416- haves_added = add_haves (negotiator , & req_buf , haves_to_send );
1487+ haves_added = add_haves (negotiator , & req_buf , haves_to_send ,
1488+ have_refs_oids );
14171489 * in_vain += haves_added ;
14181490 trace2_data_intmax ("negotiation_v2" , the_repository , "haves_added" , haves_added );
14191491 trace2_data_intmax ("negotiation_v2" , the_repository , "in_vain" , * in_vain );
@@ -1657,6 +1729,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
16571729 struct ref * ref = copy_ref_list (orig_ref );
16581730 enum fetch_state state = FETCH_CHECK_LOCAL ;
16591731 struct oidset common = OIDSET_INIT ;
1732+ struct oidset have_refs_oids = OIDSET_INIT ;
16601733 struct packet_reader reader ;
16611734 int in_vain = 0 , negotiation_started = 0 ;
16621735 int negotiation_round = 0 ;
@@ -1708,6 +1781,10 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
17081781 reader .me = "fetch-pack" ;
17091782 }
17101783
1784+ prepare_repo_settings (the_repository );
1785+ resolve_have_refs (the_repository -> settings .fetch_have_refs ,
1786+ & have_refs_oids );
1787+
17111788 while (state != FETCH_DONE ) {
17121789 switch (state ) {
17131790 case FETCH_CHECK_LOCAL :
@@ -1747,7 +1824,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
17471824 & common ,
17481825 & haves_to_send , & in_vain ,
17491826 reader .use_sideband ,
1750- seen_ack )) {
1827+ seen_ack ,
1828+ & have_refs_oids )) {
17511829 trace2_region_leave_printf ("negotiation_v2" , "round" ,
17521830 the_repository , "%d" ,
17531831 negotiation_round );
@@ -1883,6 +1961,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
18831961 negotiator -> release (negotiator );
18841962
18851963 oidset_clear (& common );
1964+ oidset_clear (& have_refs_oids );
18861965 return ref ;
18871966}
18881967
@@ -2187,6 +2266,7 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
21872266 struct packet_reader reader ;
21882267 struct object_array nt_object_array = OBJECT_ARRAY_INIT ;
21892268 struct strbuf req_buf = STRBUF_INIT ;
2269+ struct oidset have_refs_oids = OIDSET_INIT ;
21902270 int haves_to_send = INITIAL_FLUSH ;
21912271 int in_vain = 0 ;
21922272 int seen_ack = 0 ;
@@ -2205,6 +2285,10 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
22052285 add_to_object_array ,
22062286 & nt_object_array );
22072287
2288+ prepare_repo_settings (the_repository );
2289+ resolve_have_refs (the_repository -> settings .fetch_have_refs ,
2290+ & have_refs_oids );
2291+
22082292 trace2_region_enter ("fetch-pack" , "negotiate_using_fetch" , the_repository );
22092293 while (!last_iteration ) {
22102294 int haves_added ;
@@ -2221,7 +2305,8 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
22212305
22222306 packet_buf_write (& req_buf , "wait-for-done" );
22232307
2224- haves_added = add_haves (& negotiator , & req_buf , & haves_to_send );
2308+ haves_added = add_haves (& negotiator , & req_buf , & haves_to_send ,
2309+ & have_refs_oids );
22252310 in_vain += haves_added ;
22262311 if (!haves_added || (seen_ack && in_vain >= MAX_IN_VAIN ))
22272312 last_iteration = 1 ;
@@ -2273,6 +2358,7 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
22732358
22742359 clear_common_flag (acked_commits );
22752360 object_array_clear (& nt_object_array );
2361+ oidset_clear (& have_refs_oids );
22762362 negotiator .release (& negotiator );
22772363 strbuf_release (& req_buf );
22782364}
0 commit comments