Skip to content

Commit 6d08b9d

Browse files
ttaylorrgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1d89d88 commit 6d08b9d

File tree

6 files changed

+78
-3
lines changed

6 files changed

+78
-3
lines changed

Documentation/git-repack.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ this "roll-up", without respect to their reachability. This is subject
190190
to change in the future. This option (implying a drastically different
191191
repack mode) is not guaranteed to work with all other combinations of
192192
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]).
193197

194198
-m::
195199
--write-midx::

builtin/repack.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,25 @@ static void split_pack_geometry(struct pack_geometry *geometry, int factor)
423423
geometry->split = split;
424424
}
425425

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+
426445
static void clear_pack_geometry(struct pack_geometry *geometry)
427446
{
428447
if (!geometry)
@@ -468,10 +487,12 @@ static void midx_included_packs(struct string_list *include,
468487
}
469488

470489
static int write_midx_included_packs(struct string_list *include,
490+
struct pack_geometry *geometry,
471491
int show_progress, int write_bitmaps)
472492
{
473493
struct child_process cmd = CHILD_PROCESS_INIT;
474494
struct string_list_item *item;
495+
struct packed_git *largest = get_largest_active_pack(geometry);
475496
FILE *in;
476497
int ret;
477498

@@ -492,6 +513,10 @@ static int write_midx_included_packs(struct string_list *include,
492513
if (write_bitmaps)
493514
strvec_push(&cmd.args, "--bitmap");
494515

516+
if (largest)
517+
strvec_pushf(&cmd.args, "--preferred-pack=%s",
518+
pack_basename(largest));
519+
495520
ret = start_command(&cmd);
496521
if (ret)
497522
return ret;
@@ -783,7 +808,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
783808
midx_included_packs(&include, &existing_nonkept_packs,
784809
&existing_kept_packs, &names, geometry);
785810

786-
ret = write_midx_included_packs(&include,
811+
ret = write_midx_included_packs(&include, geometry,
787812
show_progress, write_bitmaps > 0);
788813

789814
string_list_clear(&include, 0);

pack-bitmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,7 @@ static int try_partial_reuse(struct packed_git *pack,
14181418
return 0;
14191419
}
14201420

1421-
static uint32_t midx_preferred_pack(struct bitmap_index *bitmap_git)
1421+
uint32_t midx_preferred_pack(struct bitmap_index *bitmap_git)
14221422
{
14231423
struct multi_pack_index *m = bitmap_git->midx;
14241424
if (!m)

pack-bitmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ int test_bitmap_commits(struct repository *r);
5555
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
5656
struct list_objects_filter_options *filter,
5757
int filter_provided_objects);
58+
uint32_t midx_preferred_pack(struct bitmap_index *bitmap_git);
5859
int reuse_partial_packfile_from_bitmap(struct bitmap_index *,
5960
struct packed_git **packfile,
6061
uint32_t *entries,

t/helper/test-read-midx.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "midx.h"
44
#include "repository.h"
55
#include "object-store.h"
6+
#include "pack-bitmap.h"
67

78
static int read_midx_file(const char *object_dir, int show_objects)
89
{
@@ -72,14 +73,36 @@ static int read_midx_checksum(const char *object_dir)
7273
return 0;
7374
}
7475

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+
7596
int cmd__read_midx(int argc, const char **argv)
7697
{
7798
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>");
79100

80101
if (!strcmp(argv[1], "--show-objects"))
81102
return read_midx_file(argv[2], 1);
82103
else if (!strcmp(argv[1], "--checksum"))
83104
return read_midx_checksum(argv[2]);
105+
else if (!strcmp(argv[1], "--preferred-pack"))
106+
return read_midx_preferred_pack(argv[2]);
84107
return read_midx_file(argv[1], 0);
85108
}

t/t7703-repack-geometric.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,26 @@ test_expect_success '--geometric ignores kept packs' '
180180
)
181181
'
182182

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+
183205
test_done

0 commit comments

Comments
 (0)