builtin/repack.c: make largest pack preferred
When repacking into a geometric series and writing a multi-pack bitmap, it is beneficial to have the largest resulting pack be the preferred object source in the bitmap's MIDX, since selecting the large packs can lead to fewer broken delta chains and better compression. Teach 'git repack' to identify this pack and pass it to the MIDX write machinery in order to mark it as preferred. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Taylor Blau committed
Sep 28, 2021 at 21:55 UTC
6d08b9d4caa230441b7d9e2b4f23deaf9ff74c13
6 files changed
+78
-3
Documentation/git-repack.txt
+4
@@ -190,6 +190,10 @@ this "roll-up", without respect to their reachability. This is subject
190
to change in the future. This option (implying a drastically different
191
repack mode) is not guaranteed to work with all other combinations of
192
option to `git repack`.
193
++
194
+When writing a multi-pack bitmap, `git repack` selects the largest resulting
195
+pack as the preferred pack for object selection by the MIDX (see
196
+linkgit:git-multi-pack-index[1]).
197
198
-m::
199
--write-midx::
builtin/repack.c
+26
-1
@@ -423,6 +423,25 @@ static void split_pack_geometry(struct pack_geometry *geometry, int factor)
423
geometry->split = split;
424
}
425
426
+static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry)
427
+{
428
+ if (!geometry) {
429
+ /*
430
+ * No geometry means either an all-into-one repack (in which
431
+ * case there is only one pack left and it is the largest) or an
432
+ * incremental one.
433
+ *
434
+ * If repacking incrementally, then we could check the size of
435
+ * all packs to determine which should be preferred, but leave
436
+ * this for later.
437
+ */
438
+ return NULL;
439
+ }
440
+ if (geometry->split == geometry->pack_nr)
441
+ return NULL;
442
+ return geometry->pack[geometry->pack_nr - 1];
443
+}
444
+
445
static void clear_pack_geometry(struct pack_geometry *geometry)
446
{
447
if (!geometry)
@@ -468,10 +487,12 @@ static void midx_included_packs(struct string_list *include,
487
}
488
489
static int write_midx_included_packs(struct string_list *include,
490
+ struct pack_geometry *geometry,
491
int show_progress, int write_bitmaps)
492
{
493
struct child_process cmd = CHILD_PROCESS_INIT;
494
struct string_list_item *item;
495
+ struct packed_git *largest = get_largest_active_pack(geometry);
496
FILE *in;
497
int ret;
498
@@ -492,6 +513,10 @@ static int write_midx_included_packs(struct string_list *include,
513
if (write_bitmaps)
514
strvec_push(&cmd.args, "--bitmap");
515
516
+ if (largest)
517
+ strvec_pushf(&cmd.args, "--preferred-pack=%s",
518
+ pack_basename(largest));
519
+
520
ret = start_command(&cmd);
521
if (ret)
522
return ret;
@@ -783,7 +808,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
808
midx_included_packs(&include, &existing_nonkept_packs,
809
&existing_kept_packs, &names, geometry);
810
786
- ret = write_midx_included_packs(&include,
811
+ ret = write_midx_included_packs(&include, geometry,
812
show_progress, write_bitmaps > 0);
813
814
string_list_clear(&include, 0);
pack-bitmap.c
+1
-1
@@ -1418,7 +1418,7 @@ static int try_partial_reuse(struct packed_git *pack,
1418
return 0;
1419
}
1420
1421
-static uint32_t midx_preferred_pack(struct bitmap_index *bitmap_git)
1421
+uint32_t midx_preferred_pack(struct bitmap_index *bitmap_git)
1422
{
1423
struct multi_pack_index *m = bitmap_git->midx;
1424
if (!m)
pack-bitmap.h
+1
@@ -55,6 +55,7 @@ int test_bitmap_commits(struct repository *r);
55
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
56
struct list_objects_filter_options *filter,
57
int filter_provided_objects);
58
+uint32_t midx_preferred_pack(struct bitmap_index *bitmap_git);
59
int reuse_partial_packfile_from_bitmap(struct bitmap_index *,
60
struct packed_git **packfile,
61
uint32_t *entries,
t/helper/test-read-midx.c
+24
-1
@@ -3,6 +3,7 @@
3
#include "midx.h"
4
#include "repository.h"
5
#include "object-store.h"
6
+#include "pack-bitmap.h"
7
8
static int read_midx_file(const char *object_dir, int show_objects)
9
{
@@ -72,14 +73,36 @@ static int read_midx_checksum(const char *object_dir)
73
return 0;
74
}
75
76
+static int read_midx_preferred_pack(const char *object_dir)
77
+{
78
+ struct multi_pack_index *midx = NULL;
79
+ struct bitmap_index *bitmap = NULL;
80
+
81
+ setup_git_directory();
82
+
83
+ midx = load_multi_pack_index(object_dir, 1);
84
+ if (!midx)
85
+ return 1;
86
+
87
+ bitmap = prepare_bitmap_git(the_repository);
88
+ if (!(bitmap && bitmap_is_midx(bitmap)))
89
+ return 1;
90
+
91
+
92
+ printf("%s\n", midx->pack_names[midx_preferred_pack(bitmap)]);
93
+ return 0;
94
+}
95
+
96
int cmd__read_midx(int argc, const char **argv)
97
{
98
if (!(argc == 2 || argc == 3))
78
- usage("read-midx [--show-objects|--checksum] <object-dir>");
99
+ usage("read-midx [--show-objects|--checksum|--preferred-pack] <object-dir>");
100
101
if (!strcmp(argv[1], "--show-objects"))
102
return read_midx_file(argv[2], 1);
103
else if (!strcmp(argv[1], "--checksum"))
104
return read_midx_checksum(argv[2]);
105
+ else if (!strcmp(argv[1], "--preferred-pack"))
106
+ return read_midx_preferred_pack(argv[2]);
107
return read_midx_file(argv[1], 0);
108
}
t/t7703-repack-geometric.sh
+22
@@ -180,4 +180,26 @@ test_expect_success '--geometric ignores kept packs' '
180
)
181
'
182
183
+test_expect_success '--geometric chooses largest MIDX preferred pack' '
184
+ git init geometric &&
185
+ test_when_finished "rm -fr geometric" &&
186
+ (
187
+ cd geometric &&
188
+
189
+ # These packs already form a geometric progression.
190
+ test_commit_bulk --start=1 1 && # 3 objects
191
+ test_commit_bulk --start=2 2 && # 6 objects
192
+ ls $objdir/pack/pack-*.idx >before &&
193
+ test_commit_bulk --start=4 4 && # 12 objects
194
+ ls $objdir/pack/pack-*.idx >after &&
195
+
196
+ git repack --geometric 2 -dbm &&
197
+
198
+ comm -3 before after | xargs -n 1 basename >expect &&
199
+ test-tool read-midx --preferred-pack $objdir >actual &&
200
+
201
+ test_cmp expect actual
202
+ )
203
+'
204
+
205
test_done