91
92
#define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + the_hash_algo->rawsz)
93
94
-struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local)
94
+static struct multi_pack_index *load_multi_pack_index_one(const char *object_dir,
95
+ const char *midx_name,
96
+ int local)
97
{
98
struct multi_pack_index *m = NULL;
99
int fd;
101
size_t midx_size;
102
void *midx_map = NULL;
103
uint32_t hash_version;
102
- struct strbuf midx_name = STRBUF_INIT;
104
uint32_t i;
105
const char *cur_pack_name;
106
struct chunkfile *cf = NULL;
107
107
- get_midx_filename(&midx_name, object_dir);
108
-
109
- fd = git_open(midx_name.buf);
108
+ fd = git_open(midx_name);
109
110
if (fd < 0)
111
goto cleanup_fail;
112
if (fstat(fd, &st)) {
114
- error_errno(_("failed to read %s"), midx_name.buf);
113
+ error_errno(_("failed to read %s"), midx_name);
114
goto cleanup_fail;
115
}
116
117
midx_size = xsize_t(st.st_size);
118
119
if (midx_size < MIDX_MIN_SIZE) {
121
- error(_("multi-pack-index file %s is too small"), midx_name.buf);
120
+ error(_("multi-pack-index file %s is too small"), midx_name);
121
goto cleanup_fail;
122
}
123
125
- strbuf_release(&midx_name);
126
-
124
midx_map = xmmap(NULL, midx_size, PROT_READ, MAP_PRIVATE, fd, 0);
125
close(fd);
126
210
211
cleanup_fail:
212
free(m);
216
- strbuf_release(&midx_name);
213
free_chunkfile(cf);
214
if (midx_map)
215
munmap(midx_map, midx_size);
218
return NULL;
219
}
220
221
+void get_midx_chain_dirname(struct strbuf *buf, const char *object_dir)
222
+{
223
+ strbuf_addf(buf, "%s/pack/multi-pack-index.d", object_dir);
224
+}
225
+
226
+void get_midx_chain_filename(struct strbuf *buf, const char *object_dir)
227
+{
228
+ get_midx_chain_dirname(buf, object_dir);
229
+ strbuf_addstr(buf, "/multi-pack-index-chain");
230
+}
231
+
232
+void get_split_midx_filename_ext(struct strbuf *buf, const char *object_dir,
233
+ const unsigned char *hash, const char *ext)
234
+{
235
+ get_midx_chain_dirname(buf, object_dir);
236
+ strbuf_addf(buf, "/multi-pack-index-%s.%s", hash_to_hex(hash), ext);
237
+}
238
+
239
+static int open_multi_pack_index_chain(const char *chain_file,
240
+ int *fd, struct stat *st)
241
+{
242
+ *fd = git_open(chain_file);
243
+ if (*fd < 0)
244
+ return 0;
245
+ if (fstat(*fd, st)) {
246
+ close(*fd);
247
+ return 0;
248
+ }
249
+ if (st->st_size < the_hash_algo->hexsz) {
250
+ close(*fd);
251
+ if (!st->st_size) {
252
+ /* treat empty files the same as missing */
253
+ errno = ENOENT;
254
+ } else {
255
+ warning(_("multi-pack-index chain file too small"));
256
+ errno = EINVAL;
257
+ }
258
+ return 0;
259
+ }
260
+ return 1;
261
+}
262
+
263
+static int add_midx_to_chain(struct multi_pack_index *midx,
264
+ struct multi_pack_index *midx_chain,
265
+ struct object_id *oids,
266
+ int n)
267
+{
268
+ if (midx_chain) {
269
+ if (unsigned_add_overflows(midx_chain->num_packs,
270
+ midx_chain->num_packs_in_base)) {
271
+ warning(_("pack count in base MIDX too high: %"PRIuMAX),
272
+ (uintmax_t)midx_chain->num_packs_in_base);
273
+ return 0;
274
+ }
275
+ if (unsigned_add_overflows(midx_chain->num_objects,
276
+ midx_chain->num_objects_in_base)) {
277
+ warning(_("object count in base MIDX too high: %"PRIuMAX),
278
+ (uintmax_t)midx_chain->num_objects_in_base);
279
+ return 0;
280
+ }
281
+ midx->num_packs_in_base = midx_chain->num_packs +
282
+ midx_chain->num_packs_in_base;
283
+ midx->num_objects_in_base = midx_chain->num_objects +
284
+ midx_chain->num_objects_in_base;
285
+ }
286
+
287
+ midx->base_midx = midx_chain;
288
+ midx->has_chain = 1;
289
+
290
+ return 1;
291
+}
292
+
293
+static struct multi_pack_index *load_midx_chain_fd_st(const char *object_dir,
294
+ int local,
295
+ int fd, struct stat *st,
296
+ int *incomplete_chain)
297
+{
298
+ struct multi_pack_index *midx_chain = NULL;
299
+ struct strbuf buf = STRBUF_INIT;
300
+ struct object_id *layers = NULL;
301
+ int valid = 1;
302
+ uint32_t i, count;
303
+ FILE *fp = xfdopen(fd, "r");
304
+
305
+ count = st->st_size / (the_hash_algo->hexsz + 1);
306
+ CALLOC_ARRAY(layers, count);
307
+
308
+ for (i = 0; i < count; i++) {
309
+ struct multi_pack_index *m;
310
+
311
+ if (strbuf_getline_lf(&buf, fp) == EOF)
312
+ break;
313
+
314
+ if (get_oid_hex(buf.buf, &layers[i])) {
315
+ warning(_("invalid multi-pack-index chain: line '%s' "
316
+ "not a hash"),
317
+ buf.buf);
318
+ valid = 0;
319
+ break;
320
+ }
321
+
322
+ valid = 0;
323
+
324
+ strbuf_reset(&buf);
325
+ get_split_midx_filename_ext(&buf, object_dir, layers[i].hash,
326
+ MIDX_EXT_MIDX);
327
+ m = load_multi_pack_index_one(object_dir, buf.buf, local);
328
+
329
+ if (m) {
330
+ if (add_midx_to_chain(m, midx_chain, layers, i)) {
331
+ midx_chain = m;
332
+ valid = 1;
333
+ } else {
334
+ close_midx(m);
335
+ }
336
+ }
337
+ if (!valid) {
338
+ warning(_("unable to find all multi-pack index files"));
339
+ break;
340
+ }
341
+ }
342
+
343
+ free(layers);
344
+ fclose(fp);
345
+ strbuf_release(&buf);
346
+
347
+ *incomplete_chain = !valid;
348
+ return midx_chain;
349
+}
350
+
351
+static struct multi_pack_index *load_multi_pack_index_chain(const char *object_dir,
352
+ int local)
353
+{
354
+ struct strbuf chain_file = STRBUF_INIT;
355
+ struct stat st;
356
+ int fd;
357
+ struct multi_pack_index *m = NULL;
358
+
359
+ get_midx_chain_filename(&chain_file, object_dir);
360
+ if (open_multi_pack_index_chain(chain_file.buf, &fd, &st)) {
361
+ int incomplete;
362
+ /* ownership of fd is taken over by load function */
363
+ m = load_midx_chain_fd_st(object_dir, local, fd, &st,
364
+ &incomplete);
365
+ }
366
+
367
+ strbuf_release(&chain_file);
368
+ return m;
369
+}
370
+
371
+struct multi_pack_index *load_multi_pack_index(const char *object_dir,
372
+ int local)
373
+{
374
+ struct strbuf midx_name = STRBUF_INIT;
375
+ struct multi_pack_index *m;
376
+
377
+ get_midx_filename(&midx_name, object_dir);
378
+
379
+ m = load_multi_pack_index_one(object_dir, midx_name.buf, local);
380
+ if (!m)
381
+ m = load_multi_pack_index_chain(object_dir, local);
382
+
383
+ strbuf_release(&midx_name);
384
+
385
+ return m;
386
+}
387
+
388
void close_midx(struct multi_pack_index *m)
389
{
390
uint32_t i;
393
return;
394
395
close_midx(m->next);
396
+ close_midx(m->base_midx);
397
398
munmap((unsigned char *)m->data, m->data_len);
399