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"
@@ -332,6 +333,40 @@ static void send_filter(struct fetch_pack_args *args,
332333 }
333334}
334335
336+ static int add_oid_to_oidset (const struct reference * ref , void * cb_data )
337+ {
338+ struct oidset * set = cb_data ;
339+ oidset_insert (set , ref -> oid );
340+ return 0 ;
341+ }
342+
343+ static void resolve_must_have (const struct string_list * must_have ,
344+ struct oidset * result )
345+ {
346+ struct string_list_item * item ;
347+
348+ if (!must_have || !must_have -> nr )
349+ return ;
350+
351+ for_each_string_list_item (item , must_have ) {
352+ if (!has_glob_specials (item -> string )) {
353+ struct object_id oid ;
354+ if (repo_get_oid (the_repository , item -> string , & oid ))
355+ continue ;
356+ if (!odb_has_object (the_repository -> objects , & oid , 0 ))
357+ continue ;
358+ oidset_insert (result , & oid );
359+ } else {
360+ struct refs_for_each_ref_options opts = {
361+ .pattern = item -> string ,
362+ };
363+ refs_for_each_ref_ext (
364+ get_main_ref_store (the_repository ),
365+ add_oid_to_oidset , result , & opts );
366+ }
367+ }
368+ }
369+
335370static int find_common (struct fetch_negotiator * negotiator ,
336371 struct fetch_pack_args * args ,
337372 int fd [2 ], struct object_id * result_oid ,
@@ -347,6 +382,7 @@ static int find_common(struct fetch_negotiator *negotiator,
347382 struct strbuf req_buf = STRBUF_INIT ;
348383 size_t state_len = 0 ;
349384 struct packet_reader reader ;
385+ struct oidset must_have_oids = OIDSET_INIT ;
350386
351387 if (args -> stateless_rpc && multi_ack == 1 )
352388 die (_ ("the option '%s' requires '%s'" ), "--stateless-rpc" , "multi_ack_detailed" );
@@ -474,7 +510,24 @@ static int find_common(struct fetch_negotiator *negotiator,
474510 trace2_region_enter ("fetch-pack" , "negotiation_v0_v1" , the_repository );
475511 flushes = 0 ;
476512 retval = -1 ;
513+
514+ /* Send unconditional haves from --must-have */
515+ resolve_must_have (args -> must_have , & must_have_oids );
516+ if (oidset_size (& must_have_oids )) {
517+ struct oidset_iter iter ;
518+ oidset_iter_init (& must_have_oids , & iter );
519+
520+ while ((oid = oidset_iter_next (& iter ))) {
521+ packet_buf_write (& req_buf , "have %s\n" ,
522+ oid_to_hex (oid ));
523+ print_verbose (args , "have %s" , oid_to_hex (oid ));
524+ }
525+ }
526+
477527 while ((oid = negotiator -> next (negotiator ))) {
528+ /* avoid duplicate oids from --must-have */
529+ if (oidset_contains (& must_have_oids , oid ))
530+ continue ;
478531 packet_buf_write (& req_buf , "have %s\n" , oid_to_hex (oid ));
479532 print_verbose (args , "have %s" , oid_to_hex (oid ));
480533 in_vain ++ ;
@@ -584,6 +637,7 @@ static int find_common(struct fetch_negotiator *negotiator,
584637 flushes ++ ;
585638 }
586639 strbuf_release (& req_buf );
640+ oidset_clear (& must_have_oids );
587641
588642 if (!got_ready || !no_done )
589643 consume_shallow_list (args , & reader );
@@ -1305,12 +1359,25 @@ static void add_common(struct strbuf *req_buf, struct oidset *common)
13051359
13061360static int add_haves (struct fetch_negotiator * negotiator ,
13071361 struct strbuf * req_buf ,
1308- int * haves_to_send )
1362+ int * haves_to_send ,
1363+ struct oidset * must_have_oids )
13091364{
13101365 int haves_added = 0 ;
13111366 const struct object_id * oid ;
13121367
1368+ /* Send unconditional haves from --must-have */
1369+ if (must_have_oids ) {
1370+ struct oidset_iter iter ;
1371+ oidset_iter_init (must_have_oids , & iter );
1372+
1373+ while ((oid = oidset_iter_next (& iter )))
1374+ packet_buf_write (req_buf , "have %s\n" ,
1375+ oid_to_hex (oid ));
1376+ }
1377+
13131378 while ((oid = negotiator -> next (negotiator ))) {
1379+ if (must_have_oids && oidset_contains (must_have_oids , oid ))
1380+ continue ;
13141381 packet_buf_write (req_buf , "have %s\n" , oid_to_hex (oid ));
13151382 if (++ haves_added >= * haves_to_send )
13161383 break ;
@@ -1358,7 +1425,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
13581425 struct fetch_pack_args * args ,
13591426 const struct ref * wants , struct oidset * common ,
13601427 int * haves_to_send , int * in_vain ,
1361- int sideband_all , int seen_ack )
1428+ int sideband_all , int seen_ack ,
1429+ struct oidset * must_have_oids )
13621430{
13631431 int haves_added ;
13641432 int done_sent = 0 ;
@@ -1413,7 +1481,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
14131481 /* Add all of the common commits we've found in previous rounds */
14141482 add_common (& req_buf , common );
14151483
1416- haves_added = add_haves (negotiator , & req_buf , haves_to_send );
1484+ haves_added = add_haves (negotiator , & req_buf , haves_to_send ,
1485+ must_have_oids );
14171486 * in_vain += haves_added ;
14181487 trace2_data_intmax ("negotiation_v2" , the_repository , "haves_added" , haves_added );
14191488 trace2_data_intmax ("negotiation_v2" , the_repository , "in_vain" , * in_vain );
@@ -1657,6 +1726,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
16571726 struct ref * ref = copy_ref_list (orig_ref );
16581727 enum fetch_state state = FETCH_CHECK_LOCAL ;
16591728 struct oidset common = OIDSET_INIT ;
1729+ struct oidset must_have_oids = OIDSET_INIT ;
16601730 struct packet_reader reader ;
16611731 int in_vain = 0 , negotiation_started = 0 ;
16621732 int negotiation_round = 0 ;
@@ -1708,6 +1778,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
17081778 reader .me = "fetch-pack" ;
17091779 }
17101780
1781+ resolve_must_have (args -> must_have , & must_have_oids );
1782+
17111783 while (state != FETCH_DONE ) {
17121784 switch (state ) {
17131785 case FETCH_CHECK_LOCAL :
@@ -1747,7 +1819,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
17471819 & common ,
17481820 & haves_to_send , & in_vain ,
17491821 reader .use_sideband ,
1750- seen_ack )) {
1822+ seen_ack ,
1823+ & must_have_oids )) {
17511824 trace2_region_leave_printf ("negotiation_v2" , "round" ,
17521825 the_repository , "%d" ,
17531826 negotiation_round );
@@ -1883,6 +1956,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
18831956 negotiator -> release (negotiator );
18841957
18851958 oidset_clear (& common );
1959+ oidset_clear (& must_have_oids );
18861960 return ref ;
18871961}
18881962
@@ -2181,12 +2255,14 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
21812255 const struct string_list * server_options ,
21822256 int stateless_rpc ,
21832257 int fd [],
2184- struct oidset * acked_commits )
2258+ struct oidset * acked_commits ,
2259+ const struct string_list * must_have )
21852260{
21862261 struct fetch_negotiator negotiator ;
21872262 struct packet_reader reader ;
21882263 struct object_array nt_object_array = OBJECT_ARRAY_INIT ;
21892264 struct strbuf req_buf = STRBUF_INIT ;
2265+ struct oidset must_have_oids = OIDSET_INIT ;
21902266 int haves_to_send = INITIAL_FLUSH ;
21912267 int in_vain = 0 ;
21922268 int seen_ack = 0 ;
@@ -2205,6 +2281,8 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
22052281 add_to_object_array ,
22062282 & nt_object_array );
22072283
2284+ resolve_must_have (must_have , & must_have_oids );
2285+
22082286 trace2_region_enter ("fetch-pack" , "negotiate_using_fetch" , the_repository );
22092287 while (!last_iteration ) {
22102288 int haves_added ;
@@ -2221,7 +2299,8 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
22212299
22222300 packet_buf_write (& req_buf , "wait-for-done" );
22232301
2224- haves_added = add_haves (& negotiator , & req_buf , & haves_to_send );
2302+ haves_added = add_haves (& negotiator , & req_buf , & haves_to_send ,
2303+ & must_have_oids );
22252304 in_vain += haves_added ;
22262305 if (!haves_added || (seen_ack && in_vain >= MAX_IN_VAIN ))
22272306 last_iteration = 1 ;
@@ -2273,6 +2352,7 @@ void negotiate_using_fetch(const struct oid_array *negotiation_tips,
22732352
22742353 clear_common_flag (acked_commits );
22752354 object_array_clear (& nt_object_array );
2355+ oidset_clear (& must_have_oids );
22762356 negotiator .release (& negotiator );
22772357 strbuf_release (& req_buf );
22782358}
0 commit comments