17
#include "refs.h"
18
#include "revision.h"
19
#include "list-objects.h"
20
+#include "path.h"
21
+#include "pack-revindex.h"
22
23
#define PACK_EXPIRED UINT_MAX
24
#define BITMAP_POS_UNKNOWN (~((uint32_t)0))
27
28
extern int midx_checksum_valid(struct multi_pack_index *m);
29
extern void clear_midx_files_ext(const char *object_dir, const char *ext,
28
- unsigned char *keep_hash);
30
+ const char *keep_hash);
31
+extern void clear_incremental_midx_files_ext(const char *object_dir,
32
+ const char *ext,
33
+ const char **keep_hashes,
34
+ uint32_t hashes_nr);
35
extern int cmp_idx_or_pack_name(const char *idx_or_pack_name,
36
const char *idx_name);
37
92
size_t nr;
93
size_t alloc;
94
struct multi_pack_index *m;
95
+ struct multi_pack_index *base_midx;
96
struct progress *progress;
97
unsigned pack_paths_checked;
98
106
107
int preferred_pack_idx;
108
109
+ int incremental;
110
+ uint32_t num_multi_pack_indexes_before;
111
+
112
struct string_list *to_include;
113
};
114
132
*/
133
if (ctx->m && midx_contains_pack(ctx->m, file_name))
134
return 0;
135
+ else if (ctx->base_midx && midx_contains_pack(ctx->base_midx,
136
+ file_name))
137
+ return 0;
138
else if (ctx->to_include &&
139
!string_list_has_string(ctx->to_include, file_name))
140
return 0;
351
for (cur_fanout = 0; cur_fanout < 256; cur_fanout++) {
352
fanout.nr = 0;
353
341
- if (ctx->m)
354
+ if (ctx->m && !ctx->incremental)
355
midx_fanout_add_midx_fanout(&fanout, ctx->m, cur_fanout,
356
ctx->preferred_pack_idx);
357
377
if (cur_object && oideq(&fanout.entries[cur_object - 1].oid,
378
&fanout.entries[cur_object].oid))
379
continue;
380
+ if (ctx->incremental && ctx->base_midx &&
381
+ midx_has_oid(ctx->base_midx,
382
+ &fanout.entries[cur_object].oid))
383
+ continue;
384
385
ALLOC_GROW(ctx->entries, st_add(ctx->entries_nr, 1),
386
alloc_objects);
564
void *data)
565
{
566
struct write_midx_context *ctx = data;
550
- uint32_t i;
567
+ uint32_t i, nr_base;
568
+
569
+ if (ctx->incremental && ctx->base_midx)
570
+ nr_base = ctx->base_midx->num_objects +
571
+ ctx->base_midx->num_objects_in_base;
572
+ else
573
+ nr_base = 0;
574
575
for (i = 0; i < ctx->entries_nr; i++)
553
- hashwrite_be32(f, ctx->pack_order[i]);
576
+ hashwrite_be32(f, ctx->pack_order[i] + nr_base);
577
578
return 0;
579
}
602
static uint32_t *midx_pack_order(struct write_midx_context *ctx)
603
{
604
struct midx_pack_order_data *data;
582
- uint32_t *pack_order;
605
+ uint32_t *pack_order, base_objects = 0;
606
uint32_t i;
607
608
trace2_region_enter("midx", "midx_pack_order", the_repository);
609
610
+ if (ctx->incremental && ctx->base_midx)
611
+ base_objects = ctx->base_midx->num_objects +
612
+ ctx->base_midx->num_objects_in_base;
613
+
614
+ ALLOC_ARRAY(pack_order, ctx->entries_nr);
615
ALLOC_ARRAY(data, ctx->entries_nr);
616
+
617
for (i = 0; i < ctx->entries_nr; i++) {
618
struct pack_midx_entry *e = &ctx->entries[i];
619
data[i].nr = i;
625
626
QSORT(data, ctx->entries_nr, midx_pack_order_cmp);
627
599
- ALLOC_ARRAY(pack_order, ctx->entries_nr);
628
for (i = 0; i < ctx->entries_nr; i++) {
629
struct pack_midx_entry *e = &ctx->entries[data[i].nr];
630
struct pack_info *pack = &ctx->info[ctx->pack_perm[e->pack_int_id]];
631
if (pack->bitmap_pos == BITMAP_POS_UNKNOWN)
604
- pack->bitmap_pos = i;
632
+ pack->bitmap_pos = i + base_objects;
633
pack->bitmap_nr++;
634
pack_order[i] = data[i].nr;
635
}
677
prepare_packing_data(the_repository, pdata);
678
679
for (i = 0; i < ctx->entries_nr; i++) {
652
- struct pack_midx_entry *from = &ctx->entries[ctx->pack_order[i]];
680
+ uint32_t pos = ctx->pack_order[i];
681
+ struct pack_midx_entry *from = &ctx->entries[pos];
682
struct object_entry *to = packlist_alloc(pdata, &from->oid);
683
684
oe_set_in_pack(pdata, to,
926
static int fill_packs_from_midx(struct write_midx_context *ctx,
927
const char *preferred_pack_name, uint32_t flags)
928
{
900
- uint32_t i;
929
+ struct multi_pack_index *m;
930
902
- for (i = 0; i < ctx->m->num_packs; i++) {
903
- ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
931
+ for (m = ctx->m; m; m = m->base_midx) {
932
+ uint32_t i;
933
+
934
+ for (i = 0; i < m->num_packs; i++) {
935
+ ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
936
905
- if (flags & MIDX_WRITE_REV_INDEX || preferred_pack_name) {
937
/*
938
* If generating a reverse index, need to have
939
* packed_git's loaded to compare their
940
* mtimes and object count.
941
*
911
- *
942
* If a preferred pack is specified, need to
943
* have packed_git's loaded to ensure the chosen
944
* preferred pack has a non-zero object count.
945
*/
916
- if (prepare_midx_pack(the_repository, ctx->m, i))
917
- return error(_("could not load pack"));
946
+ if (flags & MIDX_WRITE_REV_INDEX ||
947
+ preferred_pack_name) {
948
+ if (prepare_midx_pack(the_repository, m,
949
+ m->num_packs_in_base + i)) {
950
+ error(_("could not load pack"));
951
+ return 1;
952
+ }
953
+
954
+ if (open_pack_index(m->packs[i]))
955
+ die(_("could not open index for %s"),
956
+ m->packs[i]->pack_name);
957
+ }
958
+
959
+ fill_pack_info(&ctx->info[ctx->nr++], m->packs[i],
960
+ m->pack_names[i],
961
+ m->num_packs_in_base + i);
962
+ }
963
+ }
964
+ return 0;
965
+}
966
919
- if (open_pack_index(ctx->m->packs[i]))
920
- die(_("could not open index for %s"),
921
- ctx->m->packs[i]->pack_name);
967
+static struct {
968
+ const char *non_split;
969
+ const char *split;
970
+} midx_exts[] = {
971
+ {NULL, MIDX_EXT_MIDX},
972
+ {MIDX_EXT_BITMAP, MIDX_EXT_BITMAP},
973
+ {MIDX_EXT_REV, MIDX_EXT_REV},
974
+};
975
+
976
+static int link_midx_to_chain(struct multi_pack_index *m)
977
+{
978
+ struct strbuf from = STRBUF_INIT;
979
+ struct strbuf to = STRBUF_INIT;
980
+ int ret = 0;
981
+ size_t i;
982
+
983
+ if (!m || m->has_chain) {
984
+ /*
985
+ * Either no MIDX previously existed, or it was already
986
+ * part of a MIDX chain. In both cases, we have nothing
987
+ * to link, so return early.
988
+ */
989
+ goto done;
990
+ }
991
+
992
+ for (i = 0; i < ARRAY_SIZE(midx_exts); i++) {
993
+ const unsigned char *hash = get_midx_checksum(m);
994
+
995
+ get_midx_filename_ext(&from, m->object_dir, hash,
996
+ midx_exts[i].non_split);
997
+ get_split_midx_filename_ext(&to, m->object_dir, hash,
998
+ midx_exts[i].split);
999
+
1000
+ if (link(from.buf, to.buf) < 0 && errno != ENOENT) {
1001
+ ret = error_errno(_("unable to link '%s' to '%s'"),
1002
+ from.buf, to.buf);
1003
+ goto done;
1004
}
1005
924
- fill_pack_info(&ctx->info[ctx->nr++], ctx->m->packs[i],
925
- ctx->m->pack_names[i], i);
1006
+ strbuf_reset(&from);
1007
+ strbuf_reset(&to);
1008
}
1009
928
- return 0;
1010
+done:
1011
+ strbuf_release(&from);
1012
+ strbuf_release(&to);
1013
+ return ret;
1014
+}
1015
+
1016
+static void clear_midx_files(const char *object_dir,
1017
+ const char **hashes,
1018
+ uint32_t hashes_nr,
1019
+ unsigned incremental)
1020
+{
1021
+ /*
1022
+ * if incremental:
1023
+ * - remove all non-incremental MIDX files
1024
+ * - remove any incremental MIDX files not in the current one
1025
+ *
1026
+ * if non-incremental:
1027
+ * - remove all incremental MIDX files
1028
+ * - remove any non-incremental MIDX files not matching the current
1029
+ * hash
1030
+ */
1031
+ struct strbuf buf = STRBUF_INIT;
1032
+ const char *exts[] = { MIDX_EXT_BITMAP, MIDX_EXT_REV, MIDX_EXT_MIDX };
1033
+ uint32_t i, j;
1034
+
1035
+ for (i = 0; i < ARRAY_SIZE(exts); i++) {
1036
+ clear_incremental_midx_files_ext(object_dir, exts[i],
1037
+ hashes, hashes_nr);
1038
+ for (j = 0; j < hashes_nr; j++)
1039
+ clear_midx_files_ext(object_dir, exts[i], hashes[j]);
1040
+ }
1041
+
1042
+ if (incremental)
1043
+ get_midx_filename(&buf, object_dir);
1044
+ else
1045
+ get_midx_chain_filename(&buf, object_dir);
1046
+
1047
+ if (unlink(buf.buf) && errno != ENOENT)
1048
+ die_errno(_("failed to clear multi-pack-index at %s"), buf.buf);
1049
+
1050
+ strbuf_release(&buf);
1051
}
1052
1053
static int write_midx_internal(const char *object_dir,
1062
uint32_t i, start_pack;
1063
struct hashfile *f = NULL;
1064
struct lock_file lk;
1065
+ struct tempfile *incr;
1066
struct write_midx_context ctx = { 0 };
1067
int bitmapped_packs_concat_len = 0;
1068
int pack_name_concat_len = 0;
1069
int dropped_packs = 0;
1070
int result = 0;
1071
+ const char **keep_hashes = NULL;
1072
struct chunkfile *cf;
1073
1074
trace2_region_enter("midx", "write_midx_internal", the_repository);
1075
952
- get_midx_filename(&midx_name, object_dir);
1076
+ ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL);
1077
+ if (ctx.incremental && (flags & MIDX_WRITE_BITMAP))
1078
+ die(_("cannot write incremental MIDX with bitmap"));
1079
+
1080
+ if (ctx.incremental)
1081
+ strbuf_addf(&midx_name,
1082
+ "%s/pack/multi-pack-index.d/tmp_midx_XXXXXX",
1083
+ object_dir);
1084
+ else
1085
+ get_midx_filename(&midx_name, object_dir);
1086
if (safe_create_leading_directories(midx_name.buf))
1087
die_errno(_("unable to create leading directories of %s"),
1088
midx_name.buf);
1089
957
- if (!packs_to_include) {
958
- /*
959
- * Only reference an existing MIDX when not filtering which
960
- * packs to include, since all packs and objects are copied
961
- * blindly from an existing MIDX if one is present.
962
- */
963
- ctx.m = lookup_multi_pack_index(the_repository, object_dir);
964
- }
1090
+ if (!packs_to_include || ctx.incremental) {
1091
+ struct multi_pack_index *m = lookup_multi_pack_index(the_repository,
1092
+ object_dir);
1093
+ if (m && !midx_checksum_valid(m)) {
1094
+ warning(_("ignoring existing multi-pack-index; checksum mismatch"));
1095
+ m = NULL;
1096
+ }
1097
966
- if (ctx.m && !midx_checksum_valid(ctx.m)) {
967
- warning(_("ignoring existing multi-pack-index; checksum mismatch"));
968
- ctx.m = NULL;
1098
+ if (m) {
1099
+ /*
1100
+ * Only reference an existing MIDX when not filtering
1101
+ * which packs to include, since all packs and objects
1102
+ * are copied blindly from an existing MIDX if one is
1103
+ * present.
1104
+ */
1105
+ if (ctx.incremental)
1106
+ ctx.base_midx = m;
1107
+ else if (!packs_to_include)
1108
+ ctx.m = m;
1109
+ }
1110
}
1111
1112
ctx.nr = 0;
972
- ctx.alloc = ctx.m ? ctx.m->num_packs : 16;
1113
+ ctx.alloc = ctx.m ? ctx.m->num_packs + ctx.m->num_packs_in_base : 16;
1114
ctx.info = NULL;
1115
ALLOC_ARRAY(ctx.info, ctx.alloc);
1116
976
- if (ctx.m && fill_packs_from_midx(&ctx, preferred_pack_name,
977
- flags) < 0) {
978
- result = 1;
1117
+ if (ctx.incremental) {
1118
+ struct multi_pack_index *m = ctx.base_midx;
1119
+ while (m) {
1120
+ ctx.num_multi_pack_indexes_before++;
1121
+ m = m->base_midx;
1122
+ }
1123
+ } else if (ctx.m && fill_packs_from_midx(&ctx, preferred_pack_name,
1124
+ flags) < 0) {
1125
goto cleanup;
1126
}
1127
1138
for_each_file_in_pack_dir(object_dir, add_pack_to_midx, &ctx);
1139
stop_progress(&ctx.progress);
1140
995
- if ((ctx.m && ctx.nr == ctx.m->num_packs) &&
1141
+ if ((ctx.m && ctx.nr == ctx.m->num_packs + ctx.m->num_packs_in_base) &&
1142
+ !ctx.incremental &&
1143
!(packs_to_include || packs_to_drop)) {
1144
struct bitmap_index *bitmap_git;
1145
int bitmap_exists;
1155
* corresponding bitmap (or one wasn't requested).
1156
*/
1157
if (!want_bitmap)
1011
- clear_midx_files_ext(object_dir, ".bitmap",
1012
- NULL);
1158
+ clear_midx_files_ext(object_dir, "bitmap", NULL);
1159
goto cleanup;
1160
}
1161
}
1162
1163
+ if (ctx.incremental && !ctx.nr)
1164
+ goto cleanup; /* nothing to do */
1165
+
1166
if (preferred_pack_name) {
1167
ctx.preferred_pack_idx = -1;
1168
1308
pack_name_concat_len += MIDX_CHUNK_ALIGNMENT -
1309
(pack_name_concat_len % MIDX_CHUNK_ALIGNMENT);
1310
1162
- hold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR);
1163
- f = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));
1311
+ if (ctx.incremental) {
1312
+ struct strbuf lock_name = STRBUF_INIT;
1313
+
1314
+ get_midx_chain_filename(&lock_name, object_dir);
1315
+ hold_lock_file_for_update(&lk, lock_name.buf, LOCK_DIE_ON_ERROR);
1316
+ strbuf_release(&lock_name);
1317
+
1318
+ incr = mks_tempfile_m(midx_name.buf, 0444);
1319
+ if (!incr) {
1320
+ error(_("unable to create temporary MIDX layer"));
1321
+ return -1;
1322
+ }
1323
+
1324
+ if (adjust_shared_perm(get_tempfile_path(incr))) {
1325
+ error(_("unable to adjust shared permissions for '%s'"),
1326
+ get_tempfile_path(incr));
1327
+ return -1;
1328
+ }
1329
+
1330
+ f = hashfd(get_tempfile_fd(incr), get_tempfile_path(incr));
1331
+ } else {
1332
+ hold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR);
1333
+ f = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));
1334
+ }
1335
1336
if (ctx.nr - dropped_packs == 0) {
1337
error(_("no pack files to index."));
1424
* have been freed in the previous if block.
1425
*/
1426
1256
- if (ctx.m)
1427
+ CALLOC_ARRAY(keep_hashes, ctx.num_multi_pack_indexes_before + 1);
1428
+
1429
+ if (ctx.incremental) {
1430
+ FILE *chainf = fdopen_lock_file(&lk, "w");
1431
+ struct strbuf final_midx_name = STRBUF_INIT;
1432
+ struct multi_pack_index *m = ctx.base_midx;
1433
+
1434
+ if (!chainf) {
1435
+ error_errno(_("unable to open multi-pack-index chain file"));
1436
+ return -1;
1437
+ }
1438
+
1439
+ if (link_midx_to_chain(ctx.base_midx) < 0)
1440
+ return -1;
1441
+
1442
+ get_split_midx_filename_ext(&final_midx_name, object_dir,
1443
+ midx_hash, MIDX_EXT_MIDX);
1444
+
1445
+ if (rename_tempfile(&incr, final_midx_name.buf) < 0) {
1446
+ error_errno(_("unable to rename new multi-pack-index layer"));
1447
+ return -1;
1448
+ }
1449
+
1450
+ keep_hashes[ctx.num_multi_pack_indexes_before] =
1451
+ xstrdup(hash_to_hex(midx_hash));
1452
+
1453
+ for (i = 0; i < ctx.num_multi_pack_indexes_before; i++) {
1454
+ uint32_t j = ctx.num_multi_pack_indexes_before - i - 1;
1455
+
1456
+ keep_hashes[j] = xstrdup(hash_to_hex(get_midx_checksum(m)));
1457
+ m = m->base_midx;
1458
+ }
1459
+
1460
+ for (i = 0; i < ctx.num_multi_pack_indexes_before + 1; i++)
1461
+ fprintf(get_lock_file_fp(&lk), "%s\n", keep_hashes[i]);
1462
+ } else {
1463
+ keep_hashes[ctx.num_multi_pack_indexes_before] =
1464
+ xstrdup(hash_to_hex(midx_hash));
1465
+ }
1466
+
1467
+ if (ctx.m || ctx.base_midx)
1468
close_object_store(the_repository->objects);
1469
1470
if (commit_lock_file(&lk) < 0)
1471
die_errno(_("could not write multi-pack-index"));
1472
1262
- clear_midx_files_ext(object_dir, ".bitmap", midx_hash);
1263
- clear_midx_files_ext(object_dir, ".rev", midx_hash);
1473
+ clear_midx_files(object_dir, keep_hashes,
1474
+ ctx.num_multi_pack_indexes_before + 1,
1475
+ ctx.incremental);
1476
1477
cleanup:
1478
for (i = 0; i < ctx.nr; i++) {
1487
free(ctx.entries);
1488
free(ctx.pack_perm);
1489
free(ctx.pack_order);
1490
+ if (keep_hashes) {
1491
+ for (i = 0; i < ctx.num_multi_pack_indexes_before + 1; i++)
1492
+ free((char *)keep_hashes[i]);
1493
+ free(keep_hashes);
1494
+ }
1495
strbuf_release(&midx_name);
1496
1497
trace2_region_leave("midx", "write_midx_internal", the_repository);
1528
if (!m)
1529
return 0;
1530
1531
+ if (m->base_midx)
1532
+ die(_("cannot expire packs from an incremental multi-pack-index"));
1533
+
1534
CALLOC_ARRAY(count, m->num_packs);
1535
1536
if (flags & MIDX_PROGRESS)
1705
1706
if (!m)
1707
return 0;
1708
+ if (m->base_midx)
1709
+ die(_("cannot repack an incremental multi-pack-index"));
1710
1711
CALLOC_ARRAY(include_pack, m->num_packs);
1712