Skip to content

Commit 3f267a1

Browse files
ttaylorrgitster
authored andcommitted
builtin/pack-objects.c: respect 'pack.preferBitmapTips'
When writing a new pack with a bitmap, it is sometimes convenient to indicate some reference prefixes which should receive priority when selecting which commits to receive bitmaps. A truly motivated caller could accomplish this by setting 'pack.islandCore', (since all commits in the core island are similarly marked as preferred) but this requires callers to opt into using delta islands, which they may or may not want to do. Introduce a new multi-valued configuration, 'pack.preferBitmapTips' to allow callers to specify a list of reference prefixes. All references which have a prefix contained in 'pack.preferBitmapTips' will mark their tips as "preferred" in the same way as commits are marked as preferred for selection by 'pack.islandCore'. The choice of the verb "prefer" is intentional: marking the NEEDS_BITMAP flag on an object does *not* guarantee that that object will receive a bitmap. It merely guarantees that that commit will receive a bitmap over any *other* commit in the same window by bitmap_writer_select_commits(). The test this patch adds reflects this quirk, too. It only tests that a commit (which didn't receive bitmaps by default) is selected for bitmaps after changing the value of 'pack.preferBitmapTips' to include it. Other commits may lose their bitmaps as a byproduct of how the selection process works (bitmap_writer_select_commits() ignores the remainder of a window after seeing a commit with the NEEDS_BITMAP flag). This configuration will aide in selecting important references for multi-pack bitmaps, since they do not respect the same pack.islandCore configuration. (They could, but doing so may be confusing, since it is packs--not bitmaps--which are influenced by the delta-islands configuration). In a fork network repository (one which lists all forks of a given repository as remotes), for example, it is useful to set pack.preferBitmapTips to 'refs/remotes/<root>/heads' and 'refs/remotes/<root>/tags', where '<root>' is an opaque identifier referring to the repository which is at the base of the fork chain. Suggested-by: Jeff King <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 483fa7f commit 3f267a1

File tree

5 files changed

+96
-0
lines changed

5 files changed

+96
-0
lines changed

Documentation/config/pack.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,21 @@ pack.useSparse::
122122
commits contain certain types of direct renames. Default is
123123
`true`.
124124

125+
pack.preferBitmapTips::
126+
When selecting which commits will receive bitmaps, prefer a
127+
commit at the tip of any reference that is a suffix of any value
128+
of this configuration over any other commits in the "selection
129+
window".
130+
+
131+
Note that setting this configuration to `refs/foo` does not mean that
132+
the commits at the tips of `refs/foo/bar` and `refs/foo/baz` will
133+
necessarily be selected. This is because commits are selected for
134+
bitmaps from within a series of windows of variable length.
135+
+
136+
If a commit at the tip of any reference which is a suffix of any value
137+
of this configuration is seen in a window, it is immediately given
138+
preference over any other commit in that window.
139+
125140
pack.writeBitmaps (deprecated)::
126141
This is a deprecated synonym for `repack.writeBitmaps`.
127142

builtin/pack-objects.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3547,6 +3547,37 @@ static void record_recent_commit(struct commit *commit, void *data)
35473547
oid_array_append(&recent_objects, &commit->object.oid);
35483548
}
35493549

3550+
static int mark_bitmap_preferred_tip(const char *refname,
3551+
const struct object_id *oid, int flags,
3552+
void *_data)
3553+
{
3554+
struct object_id peeled;
3555+
struct object *object;
3556+
3557+
if (!peel_iterated_oid(oid, &peeled))
3558+
oid = &peeled;
3559+
3560+
object = parse_object_or_die(oid, refname);
3561+
if (object->type == OBJ_COMMIT)
3562+
object->flags |= NEEDS_BITMAP;
3563+
3564+
return 0;
3565+
}
3566+
3567+
static void mark_bitmap_preferred_tips(void)
3568+
{
3569+
struct string_list_item *item;
3570+
const struct string_list *preferred_tips;
3571+
3572+
preferred_tips = bitmap_preferred_tips(the_repository);
3573+
if (!preferred_tips)
3574+
return;
3575+
3576+
for_each_string_list_item(item, preferred_tips) {
3577+
for_each_ref_in(item->string, mark_bitmap_preferred_tip, NULL);
3578+
}
3579+
}
3580+
35503581
static void get_object_list(int ac, const char **av)
35513582
{
35523583
struct rev_info revs;
@@ -3601,6 +3632,9 @@ static void get_object_list(int ac, const char **av)
36013632
if (use_delta_islands)
36023633
load_delta_islands(the_repository, progress);
36033634

3635+
if (write_bitmap_index)
3636+
mark_bitmap_preferred_tips();
3637+
36043638
if (prepare_revision_walk(&revs))
36053639
die(_("revision walk setup failed"));
36063640
mark_edges_uninteresting(&revs, show_edge, sparse);

pack-bitmap.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "repository.h"
1414
#include "object-store.h"
1515
#include "list-objects-filter-options.h"
16+
#include "config.h"
1617

1718
/*
1819
* An entry on the bitmap index, representing the bitmap for a given
@@ -1529,3 +1530,8 @@ off_t get_disk_usage_from_bitmap(struct bitmap_index *bitmap_git,
15291530

15301531
return total;
15311532
}
1533+
1534+
const struct string_list *bitmap_preferred_tips(struct repository *r)
1535+
{
1536+
return repo_config_get_value_multi(r, "pack.preferbitmaptips");
1537+
}

pack-bitmap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "khash.h"
66
#include "pack.h"
77
#include "pack-objects.h"
8+
#include "string-list.h"
89

910
struct commit;
1011
struct repository;
@@ -91,4 +92,6 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
9192
const char *filename,
9293
uint16_t options);
9394

95+
const struct string_list *bitmap_preferred_tips(struct repository *r);
96+
9497
#endif

t/t5310-pack-bitmaps.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,4 +554,42 @@ test_expect_success 'fetch with bitmaps can reuse old base' '
554554
)
555555
'
556556

557+
test_expect_success 'pack.preferBitmapTips' '
558+
git init repo &&
559+
test_when_finished "rm -fr repo" &&
560+
(
561+
cd repo &&
562+
563+
# create enough commits that not all are receive bitmap
564+
# coverage even if they are all at the tip of some reference.
565+
test_commit_bulk --message="%s" 103 &&
566+
567+
git rev-list HEAD >commits.raw &&
568+
sort <commits.raw >commits &&
569+
570+
git log --format="create refs/tags/%s %H" HEAD >refs &&
571+
git update-ref --stdin <refs &&
572+
573+
git repack -adb &&
574+
test-tool bitmap list-commits | sort >bitmaps &&
575+
576+
# remember which commits did not receive bitmaps
577+
comm -13 bitmaps commits >before &&
578+
test_file_not_empty before &&
579+
580+
# mark the commits which did not receive bitmaps as preferred,
581+
# and generate the bitmap again
582+
perl -pe "s{^}{create refs/tags/include/$. }" <before |
583+
git update-ref --stdin &&
584+
git -c pack.preferBitmapTips=refs/tags/include repack -adb &&
585+
586+
# finally, check that the commit(s) without bitmap coverage
587+
# are not the same ones as before
588+
test-tool bitmap list-commits | sort >bitmaps &&
589+
comm -13 bitmaps commits >after &&
590+
591+
! test_cmp before after
592+
)
593+
'
594+
557595
test_done

0 commit comments

Comments
 (0)