Skip to content

Commit da34cc9

Browse files
committed
midx: implement writing incremental MIDX bitmaps
Now that the pack-bitmap machinery has learned how to read and interact with an incremental MIDX bitmap, teach the pack-bitmap-write.c machinery (and relevant callers from within the MIDX machinery) to write such bitmaps. The details for doing so are mostly straightforward. The main changes are as follows: - find_object_pos() now makes use of an extra MIDX parameter which is used to locate the bit positions of objects which are from previous layers (and thus do not exist in the current layer's pack_order field). (Note also that the pack_order field is moved into struct write_midx_context to further simplify the callers for write_midx_bitmap()). - bitmap_writer_build_type_index() first determines how many objects precede the current bitmap layer and offsets the bits it sets in each respective type-level bitmap by that amount so they can be OR'd together. Signed-off-by: Taylor Blau <[email protected]>
1 parent 59a50a2 commit da34cc9

5 files changed

+161
-30
lines changed

builtin/pack-objects.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,8 @@ static void write_pack_file(void)
13421342

13431343
if (write_bitmap_index) {
13441344
bitmap_writer_init(&bitmap_writer,
1345-
the_repository, &to_pack);
1345+
the_repository, &to_pack,
1346+
NULL);
13461347
bitmap_writer_set_checksum(&bitmap_writer, hash);
13471348
bitmap_writer_build_type_index(&bitmap_writer,
13481349
written_list);

midx-write.c

+23-12
Original file line numberDiff line numberDiff line change
@@ -826,20 +826,26 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr
826826
return cb.commits;
827827
}
828828

829-
static int write_midx_bitmap(const char *midx_name,
829+
static int write_midx_bitmap(struct write_midx_context *ctx,
830+
const char *object_dir, const char *midx_name,
830831
const unsigned char *midx_hash,
831832
struct packing_data *pdata,
832833
struct commit **commits,
833834
uint32_t commits_nr,
834-
uint32_t *pack_order,
835835
unsigned flags)
836836
{
837837
int ret, i;
838838
uint16_t options = 0;
839839
struct bitmap_writer writer;
840840
struct pack_idx_entry **index;
841-
char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name,
842-
hash_to_hex(midx_hash));
841+
struct strbuf bitmap_name = STRBUF_INIT;
842+
843+
if (ctx->incremental)
844+
get_split_midx_filename_ext(&bitmap_name, object_dir, midx_hash,
845+
MIDX_EXT_BITMAP);
846+
else
847+
get_midx_filename_ext(&bitmap_name, object_dir, midx_hash,
848+
MIDX_EXT_BITMAP);
843849

844850
trace2_region_enter("midx", "write_midx_bitmap", the_repository);
845851

@@ -858,7 +864,8 @@ static int write_midx_bitmap(const char *midx_name,
858864
for (i = 0; i < pdata->nr_objects; i++)
859865
index[i] = &pdata->objects[i].idx;
860866

861-
bitmap_writer_init(&writer, the_repository, pdata);
867+
bitmap_writer_init(&writer, the_repository, pdata,
868+
ctx->incremental ? ctx->base_midx : NULL);
862869
bitmap_writer_show_progress(&writer, flags & MIDX_PROGRESS);
863870
bitmap_writer_build_type_index(&writer, index);
864871

@@ -876,19 +883,19 @@ static int write_midx_bitmap(const char *midx_name,
876883
* bitmap_writer_finish().
877884
*/
878885
for (i = 0; i < pdata->nr_objects; i++)
879-
index[pack_order[i]] = &pdata->objects[i].idx;
886+
index[ctx->pack_order[i]] = &pdata->objects[i].idx;
880887

881888
bitmap_writer_select_commits(&writer, commits, commits_nr);
882889
ret = bitmap_writer_build(&writer);
883890
if (ret < 0)
884891
goto cleanup;
885892

886893
bitmap_writer_set_checksum(&writer, midx_hash);
887-
bitmap_writer_finish(&writer, index, bitmap_name, options);
894+
bitmap_writer_finish(&writer, index, bitmap_name.buf, options);
888895

889896
cleanup:
890897
free(index);
891-
free(bitmap_name);
898+
strbuf_release(&bitmap_name);
892899
bitmap_writer_free(&writer);
893900

894901
trace2_region_leave("midx", "write_midx_bitmap", the_repository);
@@ -1072,8 +1079,6 @@ static int write_midx_internal(const char *object_dir,
10721079
trace2_region_enter("midx", "write_midx_internal", the_repository);
10731080

10741081
ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL);
1075-
if (ctx.incremental && (flags & MIDX_WRITE_BITMAP))
1076-
die(_("cannot write incremental MIDX with bitmap"));
10771082

10781083
if (ctx.incremental)
10791084
strbuf_addf(&midx_name,
@@ -1115,6 +1120,12 @@ static int write_midx_internal(const char *object_dir,
11151120
if (ctx.incremental) {
11161121
struct multi_pack_index *m = ctx.base_midx;
11171122
while (m) {
1123+
if (flags & MIDX_WRITE_BITMAP && load_midx_revindex(m)) {
1124+
error(_("could not load reverse index for MIDX %s"),
1125+
hash_to_hex(get_midx_checksum(m)));
1126+
result = 1;
1127+
goto cleanup;
1128+
}
11181129
ctx.num_multi_pack_indexes_before++;
11191130
m = m->base_midx;
11201131
}
@@ -1404,8 +1415,8 @@ static int write_midx_internal(const char *object_dir,
14041415
FREE_AND_NULL(ctx.entries);
14051416
ctx.entries_nr = 0;
14061417

1407-
if (write_midx_bitmap(midx_name.buf, midx_hash, &pdata,
1408-
commits, commits_nr, ctx.pack_order,
1418+
if (write_midx_bitmap(&ctx, object_dir, midx_name.buf,
1419+
midx_hash, &pdata, commits, commits_nr,
14091420
flags) < 0) {
14101421
error(_("could not write multi-pack bitmap"));
14111422
result = 1;

pack-bitmap-write.c

+49-16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "alloc.h"
2626
#include "refs.h"
2727
#include "strmap.h"
28+
#include "midx.h"
29+
#include "pack-revindex.h"
2830

2931
struct bitmapped_commit {
3032
struct commit *commit;
@@ -42,14 +44,16 @@ static inline int bitmap_writer_nr_selected_commits(struct bitmap_writer *writer
4244
}
4345

4446
void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,
45-
struct packing_data *pdata)
47+
struct packing_data *pdata,
48+
struct multi_pack_index *midx)
4649
{
4750
memset(writer, 0, sizeof(struct bitmap_writer));
4851
if (writer->bitmaps)
4952
BUG("bitmap writer already initialized");
5053
writer->bitmaps = kh_init_oid_map();
5154
writer->pseudo_merge_commits = kh_init_oid_map();
5255
writer->to_pack = pdata;
56+
writer->midx = midx;
5357

5458
string_list_init_dup(&writer->pseudo_merge_groups);
5559

@@ -104,6 +108,11 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer,
104108
struct pack_idx_entry **index)
105109
{
106110
uint32_t i;
111+
uint32_t base_objects = 0;
112+
113+
if (writer->midx)
114+
base_objects = writer->midx->num_objects +
115+
writer->midx->num_objects_in_base;
107116

108117
writer->commits = ewah_new();
109118
writer->trees = ewah_new();
@@ -133,19 +142,19 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer,
133142

134143
switch (real_type) {
135144
case OBJ_COMMIT:
136-
ewah_set(writer->commits, i);
145+
ewah_set(writer->commits, i + base_objects);
137146
break;
138147

139148
case OBJ_TREE:
140-
ewah_set(writer->trees, i);
149+
ewah_set(writer->trees, i + base_objects);
141150
break;
142151

143152
case OBJ_BLOB:
144-
ewah_set(writer->blobs, i);
153+
ewah_set(writer->blobs, i + base_objects);
145154
break;
146155

147156
case OBJ_TAG:
148-
ewah_set(writer->tags, i);
157+
ewah_set(writer->tags, i + base_objects);
149158
break;
150159

151160
default:
@@ -198,19 +207,37 @@ void bitmap_writer_push_commit(struct bitmap_writer *writer,
198207
static uint32_t find_object_pos(struct bitmap_writer *writer,
199208
const struct object_id *oid, int *found)
200209
{
201-
struct object_entry *entry = packlist_find(writer->to_pack, oid);
210+
struct object_entry *entry;
211+
212+
entry = packlist_find(writer->to_pack, oid);
213+
if (entry) {
214+
uint32_t base_objects = 0;
215+
if (writer->midx)
216+
base_objects = writer->midx->num_objects +
217+
writer->midx->num_objects_in_base;
202218

203-
if (!entry) {
204219
if (found)
205-
*found = 0;
206-
warning("Failed to write bitmap index. Packfile doesn't have full closure "
207-
"(object %s is missing)", oid_to_hex(oid));
208-
return 0;
220+
*found = 1;
221+
return oe_in_pack_pos(writer->to_pack, entry) + base_objects;
222+
} else if (writer->midx) {
223+
uint32_t at, pos;
224+
225+
if (!bsearch_midx(oid, writer->midx, &at))
226+
goto missing;
227+
if (midx_to_pack_pos(writer->midx, at, &pos) < 0)
228+
goto missing;
229+
230+
if (found)
231+
*found = 1;
232+
return pos;
209233
}
210234

235+
missing:
211236
if (found)
212-
*found = 1;
213-
return oe_in_pack_pos(writer->to_pack, entry);
237+
*found = 0;
238+
warning("Failed to write bitmap index. Packfile doesn't have full closure "
239+
"(object %s is missing)", oid_to_hex(oid));
240+
return 0;
214241
}
215242

216243
static void compute_xor_offsets(struct bitmap_writer *writer)
@@ -577,7 +604,7 @@ int bitmap_writer_build(struct bitmap_writer *writer)
577604
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
578605
struct prio_queue tree_queue = { NULL };
579606
struct bitmap_index *old_bitmap;
580-
uint32_t *mapping;
607+
uint32_t *mapping = NULL;
581608
int closed = 1; /* until proven otherwise */
582609

583610
if (writer->show_progress)
@@ -1010,7 +1037,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10101037
struct strbuf tmp_file = STRBUF_INIT;
10111038
struct hashfile *f;
10121039
off_t *offsets = NULL;
1013-
uint32_t i;
1040+
uint32_t i, base_objects;
10141041

10151042
struct bitmap_disk_header header;
10161043

@@ -1036,6 +1063,12 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10361063
if (options & BITMAP_OPT_LOOKUP_TABLE)
10371064
CALLOC_ARRAY(offsets, writer->to_pack->nr_objects);
10381065

1066+
if (writer->midx)
1067+
base_objects = writer->midx->num_objects +
1068+
writer->midx->num_objects_in_base;
1069+
else
1070+
base_objects = 0;
1071+
10391072
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {
10401073
struct bitmapped_commit *stored = &writer->selected[i];
10411074
int commit_pos = oid_pos(&stored->commit->object.oid, index,
@@ -1044,7 +1077,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10441077

10451078
if (commit_pos < 0)
10461079
BUG(_("trying to write commit not in index"));
1047-
stored->commit_pos = commit_pos;
1080+
stored->commit_pos = commit_pos + base_objects;
10481081
}
10491082

10501083
write_selected_commits_v1(writer, f, offsets);

pack-bitmap.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct bitmap_writer {
110110

111111
kh_oid_map_t *bitmaps;
112112
struct packing_data *to_pack;
113+
struct multi_pack_index *midx; /* if appending to a MIDX chain */
113114

114115
struct bitmapped_commit *selected;
115116
unsigned int selected_nr, selected_alloc;
@@ -124,7 +125,8 @@ struct bitmap_writer {
124125
};
125126

126127
void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,
127-
struct packing_data *pdata);
128+
struct packing_data *pdata,
129+
struct multi_pack_index *midx);
128130
void bitmap_writer_show_progress(struct bitmap_writer *writer, int show);
129131
void bitmap_writer_set_checksum(struct bitmap_writer *writer,
130132
const unsigned char *sha1);

t/t5334-incremental-multi-pack-index.sh

+84
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,88 @@ test_expect_success 'convert incremental to non-incremental' '
4343

4444
compare_results_with_midx 'non-incremental MIDX conversion'
4545

46+
write_midx_layer () {
47+
n=1
48+
if test -f $midx_chain
49+
then
50+
n="$(($(wc -l <$midx_chain) + 1))"
51+
fi
52+
53+
for i in 1 2
54+
do
55+
test_commit $n.$i &&
56+
git repack -d || return 1
57+
done &&
58+
git multi-pack-index write --bitmap --incremental
59+
}
60+
61+
test_expect_success 'write initial MIDX layer' '
62+
git repack -ad &&
63+
write_midx_layer
64+
'
65+
66+
test_expect_success 'read bitmap from first MIDX layer' '
67+
git rev-list --test-bitmap 1.2
68+
'
69+
70+
test_expect_success 'write another MIDX layer' '
71+
write_midx_layer
72+
'
73+
74+
test_expect_success 'midx verify with multiple layers' '
75+
git multi-pack-index verify
76+
'
77+
78+
test_expect_success 'read bitmap from second MIDX layer' '
79+
git rev-list --test-bitmap 2.2
80+
'
81+
82+
test_expect_success 'read earlier bitmap from second MIDX layer' '
83+
git rev-list --test-bitmap 1.2
84+
'
85+
86+
test_expect_success 'show object from first pack' '
87+
git cat-file -p 1.1
88+
'
89+
90+
test_expect_success 'show object from second pack' '
91+
git cat-file -p 2.2
92+
'
93+
94+
for reuse in false single multi
95+
do
96+
test_expect_success "full clone (pack.allowPackReuse=$reuse)" '
97+
rm -fr clone.git &&
98+
99+
git config pack.allowPackReuse $reuse &&
100+
git clone --no-local --bare . clone.git
101+
'
102+
done
103+
104+
test_expect_success 'relink existing MIDX layer' '
105+
rm -fr "$midxdir" &&
106+
107+
GIT_TEST_MIDX_WRITE_REV=1 git multi-pack-index write --bitmap &&
108+
109+
midx_hash="$(test-tool read-midx --checksum $objdir)" &&
110+
111+
test_path_is_file "$packdir/multi-pack-index" &&
112+
test_path_is_file "$packdir/multi-pack-index-$midx_hash.bitmap" &&
113+
test_path_is_file "$packdir/multi-pack-index-$midx_hash.rev" &&
114+
115+
test_commit another &&
116+
git repack -d &&
117+
git multi-pack-index write --bitmap --incremental &&
118+
119+
test_path_is_missing "$packdir/multi-pack-index" &&
120+
test_path_is_missing "$packdir/multi-pack-index-$midx_hash.bitmap" &&
121+
test_path_is_missing "$packdir/multi-pack-index-$midx_hash.rev" &&
122+
123+
test_path_is_file "$midxdir/multi-pack-index-$midx_hash.midx" &&
124+
test_path_is_file "$midxdir/multi-pack-index-$midx_hash.bitmap" &&
125+
test_path_is_file "$midxdir/multi-pack-index-$midx_hash.rev" &&
126+
test_line_count = 2 "$midx_chain"
127+
128+
'
129+
46130
test_done

0 commit comments

Comments
 (0)