@@ -284,6 +284,12 @@ static struct oidmap configured_exclusions;
284
284
static struct oidset excluded_by_config ;
285
285
static int name_hash_version = -1 ;
286
286
287
+ enum stdin_packs_mode {
288
+ STDIN_PACKS_MODE_NONE ,
289
+ STDIN_PACKS_MODE_STANDARD ,
290
+ STDIN_PACKS_MODE_FOLLOW ,
291
+ };
292
+
287
293
/**
288
294
* Check whether the name_hash_version chosen by user input is appropriate,
289
295
* and also validate whether it is compatible with other features.
@@ -3725,14 +3731,14 @@ static int add_object_entry_from_pack(const struct object_id *oid,
3725
3731
return 0 ;
3726
3732
3727
3733
if (p ) {
3728
- struct rev_info * revs = _data ;
3729
3734
struct object_info oi = OBJECT_INFO_INIT ;
3730
3735
3731
3736
oi .typep = & type ;
3732
3737
if (packed_object_info (the_repository , p , ofs , & oi ) < 0 ) {
3733
3738
die (_ ("could not get type of object %s in pack %s" ),
3734
3739
oid_to_hex (oid ), p -> pack_name );
3735
3740
} else if (type == OBJ_COMMIT ) {
3741
+ struct rev_info * revs = _data ;
3736
3742
/*
3737
3743
* commits in included packs are used as starting points for the
3738
3744
* subsequent revision walk
@@ -3748,32 +3754,45 @@ static int add_object_entry_from_pack(const struct object_id *oid,
3748
3754
return 0 ;
3749
3755
}
3750
3756
3751
- static void show_commit_pack_hint (struct commit * commit UNUSED ,
3752
- void * data UNUSED )
3757
+ static void show_object_pack_hint (struct object * object , const char * name ,
3758
+ void * data )
3753
3759
{
3754
- /* nothing to do; commits don't have a namehash */
3760
+ enum stdin_packs_mode mode = * (enum stdin_packs_mode * )data ;
3761
+ if (mode == STDIN_PACKS_MODE_FOLLOW ) {
3762
+ add_object_entry (& object -> oid , object -> type , name , 0 );
3763
+ } else {
3764
+ struct object_entry * oe = packlist_find (& to_pack , & object -> oid );
3765
+ if (!oe )
3766
+ return ;
3767
+
3768
+ /*
3769
+ * Our 'to_pack' list was constructed by iterating all
3770
+ * objects packed in included packs, and so doesn't have
3771
+ * a non-zero hash field that you would typically pick
3772
+ * up during a reachability traversal.
3773
+ *
3774
+ * Make a best-effort attempt to fill in the ->hash and
3775
+ * ->no_try_delta fields here in order to perhaps
3776
+ * improve the delta selection process.
3777
+ */
3778
+ oe -> hash = pack_name_hash_fn (name );
3779
+ oe -> no_try_delta = name && no_try_delta (name );
3780
+
3781
+ stdin_packs_hints_nr ++ ;
3782
+ }
3755
3783
}
3756
3784
3757
- static void show_object_pack_hint (struct object * object , const char * name ,
3758
- void * data UNUSED )
3785
+ static void show_commit_pack_hint (struct commit * commit , void * data )
3759
3786
{
3760
- struct object_entry * oe = packlist_find (& to_pack , & object -> oid );
3761
- if (!oe )
3787
+ enum stdin_packs_mode mode = * (enum stdin_packs_mode * )data ;
3788
+
3789
+ if (mode == STDIN_PACKS_MODE_FOLLOW ) {
3790
+ show_object_pack_hint ((struct object * )commit , "" , data );
3762
3791
return ;
3792
+ }
3763
3793
3764
- /*
3765
- * Our 'to_pack' list was constructed by iterating all objects packed in
3766
- * included packs, and so doesn't have a non-zero hash field that you
3767
- * would typically pick up during a reachability traversal.
3768
- *
3769
- * Make a best-effort attempt to fill in the ->hash and ->no_try_delta
3770
- * here using a now in order to perhaps improve the delta selection
3771
- * process.
3772
- */
3773
- oe -> hash = pack_name_hash_fn (name );
3774
- oe -> no_try_delta = name && no_try_delta (name );
3794
+ /* nothing to do; commits don't have a namehash */
3775
3795
3776
- stdin_packs_hints_nr ++ ;
3777
3796
}
3778
3797
3779
3798
static int pack_mtime_cmp (const void * _a , const void * _b )
@@ -3793,32 +3812,14 @@ static int pack_mtime_cmp(const void *_a, const void *_b)
3793
3812
return 0 ;
3794
3813
}
3795
3814
3796
- static void read_packs_list_from_stdin (void )
3815
+ static void read_packs_list_from_stdin (struct rev_info * revs )
3797
3816
{
3798
3817
struct strbuf buf = STRBUF_INIT ;
3799
3818
struct string_list include_packs = STRING_LIST_INIT_DUP ;
3800
3819
struct string_list exclude_packs = STRING_LIST_INIT_DUP ;
3801
3820
struct string_list_item * item = NULL ;
3802
3821
3803
3822
struct packed_git * p ;
3804
- struct rev_info revs ;
3805
-
3806
- repo_init_revisions (the_repository , & revs , NULL );
3807
- /*
3808
- * Use a revision walk to fill in the namehash of objects in the include
3809
- * packs. To save time, we'll avoid traversing through objects that are
3810
- * in excluded packs.
3811
- *
3812
- * That may cause us to avoid populating all of the namehash fields of
3813
- * all included objects, but our goal is best-effort, since this is only
3814
- * an optimization during delta selection.
3815
- */
3816
- revs .no_kept_objects = 1 ;
3817
- revs .keep_pack_cache_flags |= IN_CORE_KEEP_PACKS ;
3818
- revs .blob_objects = 1 ;
3819
- revs .tree_objects = 1 ;
3820
- revs .tag_objects = 1 ;
3821
- revs .ignore_missing_links = 1 ;
3822
3823
3823
3824
while (strbuf_getline (& buf , stdin ) != EOF ) {
3824
3825
if (!buf .len )
@@ -3888,25 +3889,55 @@ static void read_packs_list_from_stdin(void)
3888
3889
struct packed_git * p = item -> util ;
3889
3890
for_each_object_in_pack (p ,
3890
3891
add_object_entry_from_pack ,
3891
- & revs ,
3892
+ revs ,
3892
3893
FOR_EACH_OBJECT_PACK_ORDER );
3893
3894
}
3894
3895
3896
+ strbuf_release (& buf );
3897
+ string_list_clear (& include_packs , 0 );
3898
+ string_list_clear (& exclude_packs , 0 );
3899
+ }
3900
+
3901
+ static void add_unreachable_loose_objects (struct rev_info * revs );
3902
+
3903
+ static void read_stdin_packs (enum stdin_packs_mode mode , int rev_list_unpacked )
3904
+ {
3905
+ struct rev_info revs ;
3906
+
3907
+ repo_init_revisions (the_repository , & revs , NULL );
3908
+ /*
3909
+ * Use a revision walk to fill in the namehash of objects in the include
3910
+ * packs. To save time, we'll avoid traversing through objects that are
3911
+ * in excluded packs.
3912
+ *
3913
+ * That may cause us to avoid populating all of the namehash fields of
3914
+ * all included objects, but our goal is best-effort, since this is only
3915
+ * an optimization during delta selection.
3916
+ */
3917
+ revs .no_kept_objects = 1 ;
3918
+ revs .keep_pack_cache_flags |= IN_CORE_KEEP_PACKS ;
3919
+ revs .blob_objects = 1 ;
3920
+ revs .tree_objects = 1 ;
3921
+ revs .tag_objects = 1 ;
3922
+ revs .ignore_missing_links = 1 ;
3923
+
3924
+ /* avoids adding objects in excluded packs */
3925
+ ignore_packed_keep_in_core = 1 ;
3926
+ read_packs_list_from_stdin (& revs );
3927
+ if (rev_list_unpacked )
3928
+ add_unreachable_loose_objects (& revs );
3929
+
3895
3930
if (prepare_revision_walk (& revs ))
3896
3931
die (_ ("revision walk setup failed" ));
3897
3932
traverse_commit_list (& revs ,
3898
3933
show_commit_pack_hint ,
3899
3934
show_object_pack_hint ,
3900
- NULL );
3935
+ & mode );
3901
3936
3902
3937
trace2_data_intmax ("pack-objects" , the_repository , "stdin_packs_found" ,
3903
3938
stdin_packs_found_nr );
3904
3939
trace2_data_intmax ("pack-objects" , the_repository , "stdin_packs_hints" ,
3905
3940
stdin_packs_hints_nr );
3906
-
3907
- strbuf_release (& buf );
3908
- string_list_clear (& include_packs , 0 );
3909
- string_list_clear (& exclude_packs , 0 );
3910
3941
}
3911
3942
3912
3943
static void add_cruft_object_entry (const struct object_id * oid , enum object_type type ,
@@ -4004,7 +4035,6 @@ static void mark_pack_kept_in_core(struct string_list *packs, unsigned keep)
4004
4035
}
4005
4036
}
4006
4037
4007
- static void add_unreachable_loose_objects (void );
4008
4038
static void add_objects_in_unpacked_packs (void );
4009
4039
4010
4040
static void enumerate_cruft_objects (void )
@@ -4014,7 +4044,7 @@ static void enumerate_cruft_objects(void)
4014
4044
_ ("Enumerating cruft objects" ), 0 );
4015
4045
4016
4046
add_objects_in_unpacked_packs ();
4017
- add_unreachable_loose_objects ();
4047
+ add_unreachable_loose_objects (NULL );
4018
4048
4019
4049
stop_progress (& progress_state );
4020
4050
}
@@ -4292,8 +4322,9 @@ static void add_objects_in_unpacked_packs(void)
4292
4322
}
4293
4323
4294
4324
static int add_loose_object (const struct object_id * oid , const char * path ,
4295
- void * data UNUSED )
4325
+ void * data )
4296
4326
{
4327
+ struct rev_info * revs = data ;
4297
4328
enum object_type type = oid_object_info (the_repository , oid , NULL );
4298
4329
4299
4330
if (type < 0 ) {
@@ -4314,6 +4345,10 @@ static int add_loose_object(const struct object_id *oid, const char *path,
4314
4345
} else {
4315
4346
add_object_entry (oid , type , "" , 0 );
4316
4347
}
4348
+
4349
+ if (revs && type == OBJ_COMMIT )
4350
+ add_pending_oid (revs , NULL , oid , 0 );
4351
+
4317
4352
return 0 ;
4318
4353
}
4319
4354
@@ -4322,11 +4357,10 @@ static int add_loose_object(const struct object_id *oid, const char *path,
4322
4357
* add_object_entry will weed out duplicates, so we just add every
4323
4358
* loose object we find.
4324
4359
*/
4325
- static void add_unreachable_loose_objects (void )
4360
+ static void add_unreachable_loose_objects (struct rev_info * revs )
4326
4361
{
4327
4362
for_each_loose_file_in_objdir (repo_get_object_directory (the_repository ),
4328
- add_loose_object ,
4329
- NULL , NULL , NULL );
4363
+ add_loose_object , NULL , NULL , revs );
4330
4364
}
4331
4365
4332
4366
static int has_sha1_pack_kept_or_nonlocal (const struct object_id * oid )
@@ -4673,7 +4707,7 @@ static void get_object_list(struct rev_info *revs, int ac, const char **av)
4673
4707
if (keep_unreachable )
4674
4708
add_objects_in_unpacked_packs ();
4675
4709
if (pack_loose_unreachable )
4676
- add_unreachable_loose_objects ();
4710
+ add_unreachable_loose_objects (NULL );
4677
4711
if (unpack_unreachable )
4678
4712
loosen_unused_packed_objects ();
4679
4713
@@ -4780,6 +4814,23 @@ static int is_not_in_promisor_pack(struct commit *commit, void *data) {
4780
4814
return is_not_in_promisor_pack_obj ((struct object * ) commit , data );
4781
4815
}
4782
4816
4817
+ static int parse_stdin_packs_mode (const struct option * opt , const char * arg ,
4818
+ int unset )
4819
+ {
4820
+ enum stdin_packs_mode * mode = opt -> value ;
4821
+
4822
+ if (unset )
4823
+ * mode = STDIN_PACKS_MODE_NONE ;
4824
+ else if (!arg || !* arg )
4825
+ * mode = STDIN_PACKS_MODE_STANDARD ;
4826
+ else if (!strcmp (arg , "follow" ))
4827
+ * mode = STDIN_PACKS_MODE_FOLLOW ;
4828
+ else
4829
+ die (_ ("invalid value for '%s': '%s'" ), opt -> long_name , arg );
4830
+
4831
+ return 0 ;
4832
+ }
4833
+
4783
4834
int cmd_pack_objects (int argc ,
4784
4835
const char * * argv ,
4785
4836
const char * prefix ,
@@ -4790,7 +4841,7 @@ int cmd_pack_objects(int argc,
4790
4841
struct strvec rp = STRVEC_INIT ;
4791
4842
int rev_list_unpacked = 0 , rev_list_all = 0 , rev_list_reflog = 0 ;
4792
4843
int rev_list_index = 0 ;
4793
- int stdin_packs = 0 ;
4844
+ enum stdin_packs_mode stdin_packs = STDIN_PACKS_MODE_NONE ;
4794
4845
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP ;
4795
4846
struct list_objects_filter_options filter_options =
4796
4847
LIST_OBJECTS_FILTER_INIT ;
@@ -4845,6 +4896,9 @@ int cmd_pack_objects(int argc,
4845
4896
OPT_SET_INT_F (0 , "indexed-objects" , & rev_list_index ,
4846
4897
N_ ("include objects referred to by the index" ),
4847
4898
1 , PARSE_OPT_NONEG ),
4899
+ OPT_CALLBACK_F (0 , "stdin-packs" , & stdin_packs , N_ ("mode" ),
4900
+ N_ ("read packs from stdin" ),
4901
+ PARSE_OPT_OPTARG , parse_stdin_packs_mode ),
4848
4902
OPT_BOOL (0 , "stdin-packs" , & stdin_packs ,
4849
4903
N_ ("read packs from stdin" )),
4850
4904
OPT_BOOL (0 , "stdout" , & pack_to_stdout ,
@@ -5010,9 +5064,10 @@ int cmd_pack_objects(int argc,
5010
5064
strvec_push (& rp , "--unpacked" );
5011
5065
}
5012
5066
5013
- if (exclude_promisor_objects && exclude_promisor_objects_best_effort )
5014
- die (_ ("options '%s' and '%s' cannot be used together" ),
5015
- "--exclude-promisor-objects" , "--exclude-promisor-objects-best-effort" );
5067
+ die_for_incompatible_opt2 (exclude_promisor_objects ,
5068
+ "--exclude-promisor-objects" ,
5069
+ exclude_promisor_objects_best_effort ,
5070
+ "--exclude-promisor-objects-best-effort" );
5016
5071
if (exclude_promisor_objects ) {
5017
5072
use_internal_rev_list = 1 ;
5018
5073
fetch_if_missing = 0 ;
@@ -5050,22 +5105,23 @@ int cmd_pack_objects(int argc,
5050
5105
if (!pack_to_stdout && thin )
5051
5106
die (_ ("--thin cannot be used to build an indexable pack" ));
5052
5107
5053
- if (keep_unreachable && unpack_unreachable )
5054
- die ( _ ( "options '%s' and '%s' cannot be used together" ), "--keep-unreachable" , "--unpack-unreachable" );
5108
+ die_for_incompatible_opt2 (keep_unreachable , "--keep-unreachable" ,
5109
+ unpack_unreachable , "--unpack-unreachable" );
5055
5110
if (!rev_list_all || !rev_list_reflog || !rev_list_index )
5056
5111
unpack_unreachable_expiration = 0 ;
5057
5112
5058
- if (stdin_packs && filter_options .choice )
5059
- die (_ ("cannot use --filter with --stdin-packs" ));
5113
+ die_for_incompatible_opt2 (stdin_packs , "--stdin-packs" ,
5114
+ filter_options .choice , "--filter" );
5115
+
5060
5116
5061
5117
if (stdin_packs && use_internal_rev_list )
5062
5118
die (_ ("cannot use internal rev list with --stdin-packs" ));
5063
5119
5064
5120
if (cruft ) {
5065
5121
if (use_internal_rev_list )
5066
5122
die (_ ("cannot use internal rev list with --cruft" ));
5067
- if (stdin_packs )
5068
- die ( _ ( "cannot use --stdin-packs with --cruft") );
5123
+ die_for_incompatible_opt2 (stdin_packs , "--stdin-packs" ,
5124
+ cruft , " --cruft" );
5069
5125
}
5070
5126
5071
5127
/*
@@ -5133,11 +5189,7 @@ int cmd_pack_objects(int argc,
5133
5189
progress_state = start_progress (the_repository ,
5134
5190
_ ("Enumerating objects" ), 0 );
5135
5191
if (stdin_packs ) {
5136
- /* avoids adding objects in excluded packs */
5137
- ignore_packed_keep_in_core = 1 ;
5138
- read_packs_list_from_stdin ();
5139
- if (rev_list_unpacked )
5140
- add_unreachable_loose_objects ();
5192
+ read_stdin_packs (stdin_packs , rev_list_unpacked );
5141
5193
} else if (cruft ) {
5142
5194
read_cruft_objects ();
5143
5195
} else if (!use_internal_rev_list ) {
0 commit comments