@@ -218,13 +218,19 @@ static int thin;
218
218
static int num_preferred_base ;
219
219
static struct progress * progress_state ;
220
220
221
- static struct packed_git * reuse_packfile ;
221
+ static struct bitmapped_pack * reuse_packfiles ;
222
+ static size_t reuse_packfiles_nr ;
223
+ static size_t reuse_packfiles_used_nr ;
222
224
static uint32_t reuse_packfile_objects ;
223
225
static struct bitmap * reuse_packfile_bitmap ;
224
226
225
227
static int use_bitmap_index_default = 1 ;
226
228
static int use_bitmap_index = -1 ;
227
- static int allow_pack_reuse = 1 ;
229
+ static enum {
230
+ NO_PACK_REUSE = 0 ,
231
+ SINGLE_PACK_REUSE ,
232
+ MULTI_PACK_REUSE ,
233
+ } allow_pack_reuse = SINGLE_PACK_REUSE ;
228
234
static enum {
229
235
WRITE_BITMAP_FALSE = 0 ,
230
236
WRITE_BITMAP_QUIET ,
@@ -1010,7 +1016,9 @@ static off_t find_reused_offset(off_t where)
1010
1016
return reused_chunks [lo - 1 ].difference ;
1011
1017
}
1012
1018
1013
- static void write_reused_pack_one (size_t pos , struct hashfile * out ,
1019
+ static void write_reused_pack_one (struct packed_git * reuse_packfile ,
1020
+ size_t pos , struct hashfile * out ,
1021
+ off_t pack_start ,
1014
1022
struct pack_window * * w_curs )
1015
1023
{
1016
1024
off_t offset , next , cur ;
@@ -1020,7 +1028,8 @@ static void write_reused_pack_one(size_t pos, struct hashfile *out,
1020
1028
offset = pack_pos_to_offset (reuse_packfile , pos );
1021
1029
next = pack_pos_to_offset (reuse_packfile , pos + 1 );
1022
1030
1023
- record_reused_object (offset , offset - hashfile_total (out ));
1031
+ record_reused_object (offset ,
1032
+ offset - (hashfile_total (out ) - pack_start ));
1024
1033
1025
1034
cur = offset ;
1026
1035
type = unpack_object_header (reuse_packfile , w_curs , & cur , & size );
@@ -1088,41 +1097,93 @@ static void write_reused_pack_one(size_t pos, struct hashfile *out,
1088
1097
copy_pack_data (out , reuse_packfile , w_curs , offset , next - offset );
1089
1098
}
1090
1099
1091
- static size_t write_reused_pack_verbatim (struct hashfile * out ,
1100
+ static size_t write_reused_pack_verbatim (struct bitmapped_pack * reuse_packfile ,
1101
+ struct hashfile * out ,
1102
+ off_t pack_start ,
1092
1103
struct pack_window * * w_curs )
1093
1104
{
1094
- size_t pos = 0 ;
1105
+ size_t pos = reuse_packfile -> bitmap_pos ;
1106
+ size_t end ;
1107
+
1108
+ if (pos % BITS_IN_EWORD ) {
1109
+ size_t word_pos = (pos / BITS_IN_EWORD );
1110
+ size_t offset = pos % BITS_IN_EWORD ;
1111
+ size_t last ;
1112
+ eword_t word = reuse_packfile_bitmap -> words [word_pos ];
1113
+
1114
+ if (offset + reuse_packfile -> bitmap_nr < BITS_IN_EWORD )
1115
+ last = offset + reuse_packfile -> bitmap_nr ;
1116
+ else
1117
+ last = BITS_IN_EWORD ;
1118
+
1119
+ for (; offset < last ; offset ++ ) {
1120
+ if (word >> offset == 0 )
1121
+ return word_pos ;
1122
+ if (!bitmap_get (reuse_packfile_bitmap ,
1123
+ word_pos * BITS_IN_EWORD + offset ))
1124
+ return word_pos ;
1125
+ }
1095
1126
1096
- while (pos < reuse_packfile_bitmap -> word_alloc &&
1097
- reuse_packfile_bitmap -> words [pos ] == (eword_t )~0 )
1098
- pos ++ ;
1127
+ pos += BITS_IN_EWORD - (pos % BITS_IN_EWORD );
1128
+ }
1129
+
1130
+ /*
1131
+ * Now we're going to copy as many whole eword_t's as possible.
1132
+ * "end" is the index of the last whole eword_t we copy, but
1133
+ * there may be additional bits to process. Those are handled
1134
+ * individually by write_reused_pack().
1135
+ *
1136
+ * Begin by advancing to the first word boundary in range of the
1137
+ * bit positions occupied by objects in "reuse_packfile". Then
1138
+ * pick the last word boundary in the same range. If we have at
1139
+ * least one word's worth of bits to process, continue on.
1140
+ */
1141
+ end = reuse_packfile -> bitmap_pos + reuse_packfile -> bitmap_nr ;
1142
+ if (end % BITS_IN_EWORD )
1143
+ end -= end % BITS_IN_EWORD ;
1144
+ if (pos >= end )
1145
+ return reuse_packfile -> bitmap_pos / BITS_IN_EWORD ;
1099
1146
1100
- if (pos ) {
1101
- off_t to_write ;
1147
+ while (pos < end &&
1148
+ reuse_packfile_bitmap -> words [pos / BITS_IN_EWORD ] == (eword_t )~0 )
1149
+ pos += BITS_IN_EWORD ;
1102
1150
1103
- written = (pos * BITS_IN_EWORD );
1104
- to_write = pack_pos_to_offset (reuse_packfile , written )
1105
- - sizeof (struct pack_header );
1151
+ if (pos > end )
1152
+ pos = end ;
1153
+
1154
+ if (reuse_packfile -> bitmap_pos < pos ) {
1155
+ off_t pack_start_off = pack_pos_to_offset (reuse_packfile -> p , 0 );
1156
+ off_t pack_end_off = pack_pos_to_offset (reuse_packfile -> p ,
1157
+ pos - reuse_packfile -> bitmap_pos );
1158
+
1159
+ written += pos - reuse_packfile -> bitmap_pos ;
1106
1160
1107
1161
/* We're recording one chunk, not one object. */
1108
- record_reused_object (sizeof (struct pack_header ), 0 );
1162
+ record_reused_object (pack_start_off ,
1163
+ pack_start_off - (hashfile_total (out ) - pack_start ));
1109
1164
hashflush (out );
1110
- copy_pack_data (out , reuse_packfile , w_curs ,
1111
- sizeof ( struct pack_header ), to_write );
1165
+ copy_pack_data (out , reuse_packfile -> p , w_curs ,
1166
+ pack_start_off , pack_end_off - pack_start_off );
1112
1167
1113
1168
display_progress (progress_state , written );
1114
1169
}
1115
- return pos ;
1170
+ if (pos % BITS_IN_EWORD )
1171
+ BUG ("attempted to jump past a word boundary to %" PRIuMAX ,
1172
+ (uintmax_t )pos );
1173
+ return pos / BITS_IN_EWORD ;
1116
1174
}
1117
1175
1118
- static void write_reused_pack (struct hashfile * f )
1176
+ static void write_reused_pack (struct bitmapped_pack * reuse_packfile ,
1177
+ struct hashfile * f )
1119
1178
{
1120
- size_t i = 0 ;
1179
+ size_t i = reuse_packfile -> bitmap_pos / BITS_IN_EWORD ;
1121
1180
uint32_t offset ;
1181
+ off_t pack_start = hashfile_total (f ) - sizeof (struct pack_header );
1122
1182
struct pack_window * w_curs = NULL ;
1123
1183
1124
1184
if (allow_ofs_delta )
1125
- i = write_reused_pack_verbatim (f , & w_curs );
1185
+ i = write_reused_pack_verbatim (reuse_packfile , f , pack_start ,
1186
+ & w_curs );
1126
1187
1127
1188
for (; i < reuse_packfile_bitmap -> word_alloc ; ++ i ) {
1128
1189
eword_t word = reuse_packfile_bitmap -> words [i ];
@@ -1133,16 +1194,23 @@ static void write_reused_pack(struct hashfile *f)
1133
1194
break ;
1134
1195
1135
1196
offset += ewah_bit_ctz64 (word >> offset );
1197
+ if (pos + offset < reuse_packfile -> bitmap_pos )
1198
+ continue ;
1199
+ if (pos + offset >= reuse_packfile -> bitmap_pos + reuse_packfile -> bitmap_nr )
1200
+ goto done ;
1136
1201
/*
1137
1202
* Can use bit positions directly, even for MIDX
1138
1203
* bitmaps. See comment in try_partial_reuse()
1139
1204
* for why.
1140
1205
*/
1141
- write_reused_pack_one (pos + offset , f , & w_curs );
1206
+ write_reused_pack_one (reuse_packfile -> p ,
1207
+ pos + offset - reuse_packfile -> bitmap_pos ,
1208
+ f , pack_start , & w_curs );
1142
1209
display_progress (progress_state , ++ written );
1143
1210
}
1144
1211
}
1145
1212
1213
+ done :
1146
1214
unuse_pack (& w_curs );
1147
1215
}
1148
1216
@@ -1194,9 +1262,14 @@ static void write_pack_file(void)
1194
1262
1195
1263
offset = write_pack_header (f , nr_remaining );
1196
1264
1197
- if (reuse_packfile ) {
1265
+ if (reuse_packfiles_nr ) {
1198
1266
assert (pack_to_stdout );
1199
- write_reused_pack (f );
1267
+ for (j = 0 ; j < reuse_packfiles_nr ; j ++ ) {
1268
+ reused_chunks_nr = 0 ;
1269
+ write_reused_pack (& reuse_packfiles [j ], f );
1270
+ if (reused_chunks_nr )
1271
+ reuse_packfiles_used_nr ++ ;
1272
+ }
1200
1273
offset = hashfile_total (f );
1201
1274
}
1202
1275
@@ -3172,7 +3245,19 @@ static int git_pack_config(const char *k, const char *v,
3172
3245
return 0 ;
3173
3246
}
3174
3247
if (!strcmp (k , "pack.allowpackreuse" )) {
3175
- allow_pack_reuse = git_config_bool (k , v );
3248
+ int res = git_parse_maybe_bool_text (v );
3249
+ if (res < 0 ) {
3250
+ if (!strcasecmp (v , "single" ))
3251
+ allow_pack_reuse = SINGLE_PACK_REUSE ;
3252
+ else if (!strcasecmp (v , "multi" ))
3253
+ allow_pack_reuse = MULTI_PACK_REUSE ;
3254
+ else
3255
+ die (_ ("invalid pack.allowPackReuse value: '%s'" ), v );
3256
+ } else if (res ) {
3257
+ allow_pack_reuse = SINGLE_PACK_REUSE ;
3258
+ } else {
3259
+ allow_pack_reuse = NO_PACK_REUSE ;
3260
+ }
3176
3261
return 0 ;
3177
3262
}
3178
3263
if (!strcmp (k , "pack.threads" )) {
@@ -3931,7 +4016,7 @@ static void loosen_unused_packed_objects(void)
3931
4016
*/
3932
4017
static int pack_options_allow_reuse (void )
3933
4018
{
3934
- return allow_pack_reuse &&
4019
+ return allow_pack_reuse != NO_PACK_REUSE &&
3935
4020
pack_to_stdout &&
3936
4021
!ignore_packed_keep_on_disk &&
3937
4022
!ignore_packed_keep_in_core &&
@@ -3944,13 +4029,18 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
3944
4029
if (!(bitmap_git = prepare_bitmap_walk (revs , 0 )))
3945
4030
return -1 ;
3946
4031
3947
- if (pack_options_allow_reuse () &&
3948
- !reuse_partial_packfile_from_bitmap (
3949
- bitmap_git ,
3950
- & reuse_packfile ,
3951
- & reuse_packfile_objects ,
3952
- & reuse_packfile_bitmap )) {
3953
- assert (reuse_packfile_objects );
4032
+ if (pack_options_allow_reuse ())
4033
+ reuse_partial_packfile_from_bitmap (bitmap_git ,
4034
+ & reuse_packfiles ,
4035
+ & reuse_packfiles_nr ,
4036
+ & reuse_packfile_bitmap ,
4037
+ allow_pack_reuse == MULTI_PACK_REUSE );
4038
+
4039
+ if (reuse_packfiles ) {
4040
+ reuse_packfile_objects = bitmap_popcount (reuse_packfile_bitmap );
4041
+ if (!reuse_packfile_objects )
4042
+ BUG ("expected non-empty reuse bitmap" );
4043
+
3954
4044
nr_result += reuse_packfile_objects ;
3955
4045
nr_seen += reuse_packfile_objects ;
3956
4046
display_progress (progress_state , nr_seen );
@@ -4518,11 +4608,20 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
4518
4608
fprintf_ln (stderr ,
4519
4609
_ ("Total %" PRIu32 " (delta %" PRIu32 "),"
4520
4610
" reused %" PRIu32 " (delta %" PRIu32 "),"
4521
- " pack-reused %" PRIu32 ),
4611
+ " pack-reused %" PRIu32 " (from %" PRIuMAX ")" ),
4522
4612
written , written_delta , reused , reused_delta ,
4523
- reuse_packfile_objects );
4613
+ reuse_packfile_objects ,
4614
+ (uintmax_t )reuse_packfiles_used_nr );
4615
+
4616
+ trace2_data_intmax ("pack-objects" , the_repository , "written" , written );
4617
+ trace2_data_intmax ("pack-objects" , the_repository , "written/delta" , written_delta );
4618
+ trace2_data_intmax ("pack-objects" , the_repository , "reused" , reused );
4619
+ trace2_data_intmax ("pack-objects" , the_repository , "reused/delta" , reused_delta );
4620
+ trace2_data_intmax ("pack-objects" , the_repository , "pack-reused" , reuse_packfile_objects );
4621
+ trace2_data_intmax ("pack-objects" , the_repository , "packs-reused" , reuse_packfiles_used_nr );
4524
4622
4525
4623
cleanup :
4624
+ clear_packing_data (& to_pack );
4526
4625
list_objects_filter_release (& filter_options );
4527
4626
strvec_clear (& rp );
4528
4627
0 commit comments