diff options
author | Taylor Blau <me@ttaylorr.com> | 2021-09-29 01:55:07 (GMT) |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2021-09-29 04:20:56 (GMT) |
commit | 08944d1c221a7f4fe42a50c0f11f129769edc9b1 (patch) | |
tree | bfc49387cf4e163608ed10c7cd805d891fb61a0f /midx.c | |
parent | 6fb22ca463077a07f42675be52e68891f319b5c2 (diff) | |
download | git-08944d1c221a7f4fe42a50c0f11f129769edc9b1.zip git-08944d1c221a7f4fe42a50c0f11f129769edc9b1.tar.gz git-08944d1c221a7f4fe42a50c0f11f129769edc9b1.tar.bz2 |
midx: preliminary support for `--refs-snapshot`
To figure out which commits we can write a bitmap for, the multi-pack
index/bitmap code does a reachability traversal, marking any commit
which can be found in the MIDX as eligible to receive a bitmap.
This approach will cause a problem when multi-pack bitmaps are able to
be generated from `git repack`, since the reference tips can change
during the repack. Even though we ignore commits that don't exist in
the MIDX (when doing a scan of the ref tips), it's possible that a
commit in the MIDX reaches something that isn't.
This can happen when a multi-pack index contains some pack which refers
to loose objects (e.g., if a pack was pushed after starting the repack
but before generating the MIDX which depends on an object which is
stored as loose in the repository, and by definition isn't included in
the multi-pack index).
By taking a snapshot of the references before we start repacking, we can
close that race window. In the above scenario (where we have a packed
object pointing at a loose one), we'll either (a) take a snapshot of the
references before seeing the packed one, or (b) take it after, at which
point we can guarantee that the loose object will be packed and included
in the MIDX.
This patch does just that. It writes a temporary "reference snapshot",
which is a list of OIDs that are at the ref tips before writing a
multi-pack bitmap. References that are "preferred" (i.e,. are a suffix
of at least one value of the 'pack.preferBitmapTips' configuration) are
marked with a special '+'.
The format is simple: one line per commit at each tip, with an optional
'+' at the beginning (for preferred references, as described above).
When provided, the reference snapshot is used to drive bitmap selection
instead of the MIDX code doing its own traversal. When it isn't
provided, the usual traversal takes place instead.
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'midx.c')
-rw-r--r-- | midx.c | 61 |
1 files changed, 53 insertions, 8 deletions
@@ -983,7 +983,43 @@ static void bitmap_show_commit(struct commit *commit, void *_data) data->commits[data->commits_nr++] = commit; } +static int read_refs_snapshot(const char *refs_snapshot, + struct rev_info *revs) +{ + struct strbuf buf = STRBUF_INIT; + struct object_id oid; + FILE *f = xfopen(refs_snapshot, "r"); + + while (strbuf_getline(&buf, f) != EOF) { + struct object *object; + int preferred = 0; + char *hex = buf.buf; + const char *end = NULL; + + if (buf.len && *buf.buf == '+') { + preferred = 1; + hex = &buf.buf[1]; + } + + if (parse_oid_hex(hex, &oid, &end) < 0) + die(_("could not parse line: %s"), buf.buf); + if (*end) + die(_("malformed line: %s"), buf.buf); + + object = parse_object_or_die(&oid, NULL); + if (preferred) + object->flags |= NEEDS_BITMAP; + + add_pending_object(revs, object, ""); + } + + fclose(f); + strbuf_release(&buf); + return 0; +} + static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr_p, + const char *refs_snapshot, struct write_midx_context *ctx) { struct rev_info revs; @@ -992,8 +1028,12 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr cb.ctx = ctx; repo_init_revisions(the_repository, &revs, NULL); - setup_revisions(0, NULL, &revs, NULL); - for_each_ref(add_ref_to_pending, &revs); + if (refs_snapshot) { + read_refs_snapshot(refs_snapshot, &revs); + } else { + setup_revisions(0, NULL, &revs, NULL); + for_each_ref(add_ref_to_pending, &revs); + } /* * Skipping promisor objects here is intentional, since it only excludes @@ -1022,6 +1062,7 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr static int write_midx_bitmap(char *midx_name, unsigned char *midx_hash, struct write_midx_context *ctx, + const char *refs_snapshot, unsigned flags) { struct packing_data pdata; @@ -1033,7 +1074,7 @@ static int write_midx_bitmap(char *midx_name, unsigned char *midx_hash, prepare_midx_packing_data(&pdata, ctx); - commits = find_commits_for_midx_bitmap(&commits_nr, ctx); + commits = find_commits_for_midx_bitmap(&commits_nr, refs_snapshot, ctx); /* * Build the MIDX-order index based on pdata.objects (which is already @@ -1081,6 +1122,7 @@ static int write_midx_internal(const char *object_dir, struct string_list *packs_to_include, struct string_list *packs_to_drop, const char *preferred_pack_name, + const char *refs_snapshot, unsigned flags) { char *midx_name; @@ -1374,7 +1416,8 @@ static int write_midx_internal(const char *object_dir, if (flags & MIDX_WRITE_REV_INDEX) write_midx_reverse_index(midx_name, midx_hash, &ctx); if (flags & MIDX_WRITE_BITMAP) { - if (write_midx_bitmap(midx_name, midx_hash, &ctx, flags) < 0) { + if (write_midx_bitmap(midx_name, midx_hash, &ctx, + refs_snapshot, flags) < 0) { error(_("could not write multi-pack bitmap")); result = 1; goto cleanup; @@ -1409,19 +1452,21 @@ cleanup: int write_midx_file(const char *object_dir, const char *preferred_pack_name, + const char *refs_snapshot, unsigned flags) { return write_midx_internal(object_dir, NULL, NULL, preferred_pack_name, - flags); + refs_snapshot, flags); } int write_midx_file_only(const char *object_dir, struct string_list *packs_to_include, const char *preferred_pack_name, + const char *refs_snapshot, unsigned flags) { return write_midx_internal(object_dir, packs_to_include, NULL, - preferred_pack_name, flags); + preferred_pack_name, refs_snapshot, flags); } struct clear_midx_data { @@ -1701,7 +1746,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla free(count); if (packs_to_drop.nr) { - result = write_midx_internal(object_dir, NULL, &packs_to_drop, NULL, flags); + result = write_midx_internal(object_dir, NULL, &packs_to_drop, NULL, NULL, flags); m = NULL; } @@ -1892,7 +1937,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size, goto cleanup; } - result = write_midx_internal(object_dir, NULL, NULL, NULL, flags); + result = write_midx_internal(object_dir, NULL, NULL, NULL, NULL, flags); m = NULL; cleanup: |