@@ -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.
@@ -3727,14 +3733,14 @@ static int add_object_entry_from_pack(const struct object_id *oid,
3727
3733
return 0 ;
3728
3734
3729
3735
if (p ) {
3730
- struct rev_info * revs = _data ;
3731
3736
struct object_info oi = OBJECT_INFO_INIT ;
3732
3737
3733
3738
oi .typep = & type ;
3734
3739
if (packed_object_info (the_repository , p , ofs , & oi ) < 0 ) {
3735
3740
die (_ ("could not get type of object %s in pack %s" ),
3736
3741
oid_to_hex (oid ), p -> pack_name );
3737
3742
} else if (type == OBJ_COMMIT ) {
3743
+ struct rev_info * revs = _data ;
3738
3744
/*
3739
3745
* commits in included packs are used as starting points for the
3740
3746
* subsequent revision walk
@@ -3750,32 +3756,48 @@ static int add_object_entry_from_pack(const struct object_id *oid,
3750
3756
return 0 ;
3751
3757
}
3752
3758
3753
- static void show_commit_pack_hint (struct commit * commit UNUSED ,
3754
- void * data UNUSED )
3759
+ static void show_object_pack_hint (struct object * object , const char * name ,
3760
+ void * data )
3755
3761
{
3756
- /* nothing to do; commits don't have a namehash */
3762
+ enum stdin_packs_mode mode = * (enum stdin_packs_mode * )data ;
3763
+ if (mode == STDIN_PACKS_MODE_FOLLOW ) {
3764
+ if (object -> type == OBJ_BLOB &&
3765
+ !has_object (the_repository , & object -> oid , 0 ))
3766
+ return ;
3767
+ add_object_entry (& object -> oid , object -> type , name , 0 );
3768
+ } else {
3769
+ struct object_entry * oe = packlist_find (& to_pack , & object -> oid );
3770
+ if (!oe )
3771
+ return ;
3772
+
3773
+ /*
3774
+ * Our 'to_pack' list was constructed by iterating all
3775
+ * objects packed in included packs, and so doesn't have
3776
+ * a non-zero hash field that you would typically pick
3777
+ * up during a reachability traversal.
3778
+ *
3779
+ * Make a best-effort attempt to fill in the ->hash and
3780
+ * ->no_try_delta fields here in order to perhaps
3781
+ * improve the delta selection process.
3782
+ */
3783
+ oe -> hash = pack_name_hash_fn (name );
3784
+ oe -> no_try_delta = name && no_try_delta (name );
3785
+
3786
+ stdin_packs_hints_nr ++ ;
3787
+ }
3757
3788
}
3758
3789
3759
- static void show_object_pack_hint (struct object * object , const char * name ,
3760
- void * data UNUSED )
3790
+ static void show_commit_pack_hint (struct commit * commit , void * data )
3761
3791
{
3762
- struct object_entry * oe = packlist_find (& to_pack , & object -> oid );
3763
- if (!oe )
3792
+ enum stdin_packs_mode mode = * (enum stdin_packs_mode * )data ;
3793
+
3794
+ if (mode == STDIN_PACKS_MODE_FOLLOW ) {
3795
+ show_object_pack_hint ((struct object * )commit , "" , data );
3764
3796
return ;
3797
+ }
3765
3798
3766
- /*
3767
- * Our 'to_pack' list was constructed by iterating all objects packed in
3768
- * included packs, and so doesn't have a non-zero hash field that you
3769
- * would typically pick up during a reachability traversal.
3770
- *
3771
- * Make a best-effort attempt to fill in the ->hash and ->no_try_delta
3772
- * here using a now in order to perhaps improve the delta selection
3773
- * process.
3774
- */
3775
- oe -> hash = pack_name_hash_fn (name );
3776
- oe -> no_try_delta = name && no_try_delta (name );
3799
+ /* nothing to do; commits don't have a namehash */
3777
3800
3778
- stdin_packs_hints_nr ++ ;
3779
3801
}
3780
3802
3781
3803
static int pack_mtime_cmp (const void * _a , const void * _b )
@@ -3795,32 +3817,14 @@ static int pack_mtime_cmp(const void *_a, const void *_b)
3795
3817
return 0 ;
3796
3818
}
3797
3819
3798
- static void read_packs_list_from_stdin (void )
3820
+ static void read_packs_list_from_stdin (struct rev_info * revs )
3799
3821
{
3800
3822
struct strbuf buf = STRBUF_INIT ;
3801
3823
struct string_list include_packs = STRING_LIST_INIT_DUP ;
3802
3824
struct string_list exclude_packs = STRING_LIST_INIT_DUP ;
3803
3825
struct string_list_item * item = NULL ;
3804
3826
3805
3827
struct packed_git * p ;
3806
- struct rev_info revs ;
3807
-
3808
- repo_init_revisions (the_repository , & revs , NULL );
3809
- /*
3810
- * Use a revision walk to fill in the namehash of objects in the include
3811
- * packs. To save time, we'll avoid traversing through objects that are
3812
- * in excluded packs.
3813
- *
3814
- * That may cause us to avoid populating all of the namehash fields of
3815
- * all included objects, but our goal is best-effort, since this is only
3816
- * an optimization during delta selection.
3817
- */
3818
- revs .no_kept_objects = 1 ;
3819
- revs .keep_pack_cache_flags |= IN_CORE_KEEP_PACKS ;
3820
- revs .blob_objects = 1 ;
3821
- revs .tree_objects = 1 ;
3822
- revs .tag_objects = 1 ;
3823
- revs .ignore_missing_links = 1 ;
3824
3828
3825
3829
while (strbuf_getline (& buf , stdin ) != EOF ) {
3826
3830
if (!buf .len )
@@ -3890,25 +3894,55 @@ static void read_packs_list_from_stdin(void)
3890
3894
struct packed_git * p = item -> util ;
3891
3895
for_each_object_in_pack (p ,
3892
3896
add_object_entry_from_pack ,
3893
- & revs ,
3897
+ revs ,
3894
3898
FOR_EACH_OBJECT_PACK_ORDER );
3895
3899
}
3896
3900
3901
+ strbuf_release (& buf );
3902
+ string_list_clear (& include_packs , 0 );
3903
+ string_list_clear (& exclude_packs , 0 );
3904
+ }
3905
+
3906
+ static void add_unreachable_loose_objects (struct rev_info * revs );
3907
+
3908
+ static void read_stdin_packs (enum stdin_packs_mode mode , int rev_list_unpacked )
3909
+ {
3910
+ struct rev_info revs ;
3911
+
3912
+ repo_init_revisions (the_repository , & revs , NULL );
3913
+ /*
3914
+ * Use a revision walk to fill in the namehash of objects in the include
3915
+ * packs. To save time, we'll avoid traversing through objects that are
3916
+ * in excluded packs.
3917
+ *
3918
+ * That may cause us to avoid populating all of the namehash fields of
3919
+ * all included objects, but our goal is best-effort, since this is only
3920
+ * an optimization during delta selection.
3921
+ */
3922
+ revs .no_kept_objects = 1 ;
3923
+ revs .keep_pack_cache_flags |= IN_CORE_KEEP_PACKS ;
3924
+ revs .blob_objects = 1 ;
3925
+ revs .tree_objects = 1 ;
3926
+ revs .tag_objects = 1 ;
3927
+ revs .ignore_missing_links = 1 ;
3928
+
3929
+ /* avoids adding objects in excluded packs */
3930
+ ignore_packed_keep_in_core = 1 ;
3931
+ read_packs_list_from_stdin (& revs );
3932
+ if (rev_list_unpacked )
3933
+ add_unreachable_loose_objects (& revs );
3934
+
3897
3935
if (prepare_revision_walk (& revs ))
3898
3936
die (_ ("revision walk setup failed" ));
3899
3937
traverse_commit_list (& revs ,
3900
3938
show_commit_pack_hint ,
3901
3939
show_object_pack_hint ,
3902
- NULL );
3940
+ & mode );
3903
3941
3904
3942
trace2_data_intmax ("pack-objects" , the_repository , "stdin_packs_found" ,
3905
3943
stdin_packs_found_nr );
3906
3944
trace2_data_intmax ("pack-objects" , the_repository , "stdin_packs_hints" ,
3907
3945
stdin_packs_hints_nr );
3908
-
3909
- strbuf_release (& buf );
3910
- string_list_clear (& include_packs , 0 );
3911
- string_list_clear (& exclude_packs , 0 );
3912
3946
}
3913
3947
3914
3948
static void add_cruft_object_entry (const struct object_id * oid , enum object_type type ,
@@ -4006,7 +4040,6 @@ static void mark_pack_kept_in_core(struct string_list *packs, unsigned keep)
4006
4040
}
4007
4041
}
4008
4042
4009
- static void add_unreachable_loose_objects (void );
4010
4043
static void add_objects_in_unpacked_packs (void );
4011
4044
4012
4045
static void enumerate_cruft_objects (void )
@@ -4016,7 +4049,7 @@ static void enumerate_cruft_objects(void)
4016
4049
_ ("Enumerating cruft objects" ), 0 );
4017
4050
4018
4051
add_objects_in_unpacked_packs ();
4019
- add_unreachable_loose_objects ();
4052
+ add_unreachable_loose_objects (NULL );
4020
4053
4021
4054
stop_progress (& progress_state );
4022
4055
}
@@ -4294,8 +4327,9 @@ static void add_objects_in_unpacked_packs(void)
4294
4327
}
4295
4328
4296
4329
static int add_loose_object (const struct object_id * oid , const char * path ,
4297
- void * data UNUSED )
4330
+ void * data )
4298
4331
{
4332
+ struct rev_info * revs = data ;
4299
4333
enum object_type type = odb_read_object_info (the_repository -> objects , oid , NULL );
4300
4334
4301
4335
if (type < 0 ) {
@@ -4316,6 +4350,10 @@ static int add_loose_object(const struct object_id *oid, const char *path,
4316
4350
} else {
4317
4351
add_object_entry (oid , type , "" , 0 );
4318
4352
}
4353
+
4354
+ if (revs && type == OBJ_COMMIT )
4355
+ add_pending_oid (revs , NULL , oid , 0 );
4356
+
4319
4357
return 0 ;
4320
4358
}
4321
4359
@@ -4324,11 +4362,10 @@ static int add_loose_object(const struct object_id *oid, const char *path,
4324
4362
* add_object_entry will weed out duplicates, so we just add every
4325
4363
* loose object we find.
4326
4364
*/
4327
- static void add_unreachable_loose_objects (void )
4365
+ static void add_unreachable_loose_objects (struct rev_info * revs )
4328
4366
{
4329
4367
for_each_loose_file_in_objdir (repo_get_object_directory (the_repository ),
4330
- add_loose_object ,
4331
- NULL , NULL , NULL );
4368
+ add_loose_object , NULL , NULL , revs );
4332
4369
}
4333
4370
4334
4371
static int has_sha1_pack_kept_or_nonlocal (const struct object_id * oid )
@@ -4675,7 +4712,7 @@ static void get_object_list(struct rev_info *revs, int ac, const char **av)
4675
4712
if (keep_unreachable )
4676
4713
add_objects_in_unpacked_packs ();
4677
4714
if (pack_loose_unreachable )
4678
- add_unreachable_loose_objects ();
4715
+ add_unreachable_loose_objects (NULL );
4679
4716
if (unpack_unreachable )
4680
4717
loosen_unused_packed_objects ();
4681
4718
@@ -4782,6 +4819,23 @@ static int is_not_in_promisor_pack(struct commit *commit, void *data) {
4782
4819
return is_not_in_promisor_pack_obj ((struct object * ) commit , data );
4783
4820
}
4784
4821
4822
+ static int parse_stdin_packs_mode (const struct option * opt , const char * arg ,
4823
+ int unset )
4824
+ {
4825
+ enum stdin_packs_mode * mode = opt -> value ;
4826
+
4827
+ if (unset )
4828
+ * mode = STDIN_PACKS_MODE_NONE ;
4829
+ else if (!arg || !* arg )
4830
+ * mode = STDIN_PACKS_MODE_STANDARD ;
4831
+ else if (!strcmp (arg , "follow" ))
4832
+ * mode = STDIN_PACKS_MODE_FOLLOW ;
4833
+ else
4834
+ die (_ ("invalid value for '%s': '%s'" ), opt -> long_name , arg );
4835
+
4836
+ return 0 ;
4837
+ }
4838
+
4785
4839
int cmd_pack_objects (int argc ,
4786
4840
const char * * argv ,
4787
4841
const char * prefix ,
@@ -4792,7 +4846,7 @@ int cmd_pack_objects(int argc,
4792
4846
struct strvec rp = STRVEC_INIT ;
4793
4847
int rev_list_unpacked = 0 , rev_list_all = 0 , rev_list_reflog = 0 ;
4794
4848
int rev_list_index = 0 ;
4795
- int stdin_packs = 0 ;
4849
+ enum stdin_packs_mode stdin_packs = STDIN_PACKS_MODE_NONE ;
4796
4850
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP ;
4797
4851
struct list_objects_filter_options filter_options =
4798
4852
LIST_OBJECTS_FILTER_INIT ;
@@ -4847,6 +4901,9 @@ int cmd_pack_objects(int argc,
4847
4901
OPT_SET_INT_F (0 , "indexed-objects" , & rev_list_index ,
4848
4902
N_ ("include objects referred to by the index" ),
4849
4903
1 , PARSE_OPT_NONEG ),
4904
+ OPT_CALLBACK_F (0 , "stdin-packs" , & stdin_packs , N_ ("mode" ),
4905
+ N_ ("read packs from stdin" ),
4906
+ PARSE_OPT_OPTARG , parse_stdin_packs_mode ),
4850
4907
OPT_BOOL (0 , "stdin-packs" , & stdin_packs ,
4851
4908
N_ ("read packs from stdin" )),
4852
4909
OPT_BOOL (0 , "stdout" , & pack_to_stdout ,
@@ -5012,9 +5069,10 @@ int cmd_pack_objects(int argc,
5012
5069
strvec_push (& rp , "--unpacked" );
5013
5070
}
5014
5071
5015
- if (exclude_promisor_objects && exclude_promisor_objects_best_effort )
5016
- die (_ ("options '%s' and '%s' cannot be used together" ),
5017
- "--exclude-promisor-objects" , "--exclude-promisor-objects-best-effort" );
5072
+ die_for_incompatible_opt2 (exclude_promisor_objects ,
5073
+ "--exclude-promisor-objects" ,
5074
+ exclude_promisor_objects_best_effort ,
5075
+ "--exclude-promisor-objects-best-effort" );
5018
5076
if (exclude_promisor_objects ) {
5019
5077
use_internal_rev_list = 1 ;
5020
5078
fetch_if_missing = 0 ;
@@ -5052,22 +5110,23 @@ int cmd_pack_objects(int argc,
5052
5110
if (!pack_to_stdout && thin )
5053
5111
die (_ ("--thin cannot be used to build an indexable pack" ));
5054
5112
5055
- if (keep_unreachable && unpack_unreachable )
5056
- die ( _ ( "options '%s' and '%s' cannot be used together" ), "--keep-unreachable" , "--unpack-unreachable" );
5113
+ die_for_incompatible_opt2 (keep_unreachable , "--keep-unreachable" ,
5114
+ unpack_unreachable , "--unpack-unreachable" );
5057
5115
if (!rev_list_all || !rev_list_reflog || !rev_list_index )
5058
5116
unpack_unreachable_expiration = 0 ;
5059
5117
5060
- if (stdin_packs && filter_options .choice )
5061
- die (_ ("cannot use --filter with --stdin-packs" ));
5118
+ die_for_incompatible_opt2 (stdin_packs , "--stdin-packs" ,
5119
+ filter_options .choice , "--filter" );
5120
+
5062
5121
5063
5122
if (stdin_packs && use_internal_rev_list )
5064
5123
die (_ ("cannot use internal rev list with --stdin-packs" ));
5065
5124
5066
5125
if (cruft ) {
5067
5126
if (use_internal_rev_list )
5068
5127
die (_ ("cannot use internal rev list with --cruft" ));
5069
- if (stdin_packs )
5070
- die ( _ ( "cannot use --stdin-packs with --cruft") );
5128
+ die_for_incompatible_opt2 (stdin_packs , "--stdin-packs" ,
5129
+ cruft , " --cruft" );
5071
5130
}
5072
5131
5073
5132
/*
@@ -5135,11 +5194,7 @@ int cmd_pack_objects(int argc,
5135
5194
progress_state = start_progress (the_repository ,
5136
5195
_ ("Enumerating objects" ), 0 );
5137
5196
if (stdin_packs ) {
5138
- /* avoids adding objects in excluded packs */
5139
- ignore_packed_keep_in_core = 1 ;
5140
- read_packs_list_from_stdin ();
5141
- if (rev_list_unpacked )
5142
- add_unreachable_loose_objects ();
5197
+ read_stdin_packs (stdin_packs , rev_list_unpacked );
5143
5198
} else if (cruft ) {
5144
5199
read_cruft_objects ();
5145
5200
} else if (!use_internal_rev_list ) {
0 commit comments