Skip to content

Commit 48034db

Browse files
committed
Merge branch 'tb/pack-path-walk-bitmap-delta-islands' into seen
The pack-objects command now supports using reachability bitmaps and delta-islands concurrently with the `--path-walk` option, allowing faster packaging by falling back to path-walk when bitmaps cannot fully satisfy the request. * tb/pack-path-walk-bitmap-delta-islands: pack-objects: support `--delta-islands` with `--path-walk` pack-objects: extract `record_tree_depth()` helper pack-objects: support reachability bitmaps with `--path-walk`
2 parents 174f35c + 988384f commit 48034db

4 files changed

Lines changed: 122 additions & 23 deletions

File tree

Documentation/git-pack-objects.adoc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,13 @@ will be automatically changed to version `1`.
402402
of filenames that cause collisions in Git's default name-hash
403403
algorithm.
404404
+
405-
Incompatible with `--delta-islands`. The `--use-bitmap-index` option is
406-
ignored in the presence of `--path-walk`. The `--path-walk` option
407-
supports the `--filter=<spec>` forms `blob:none`, `blob:limit=<n>`,
408-
`tree:0`, `object:type=<type>`, and `sparse:<oid>`. These supported filter
409-
types can be combined with the `combine:<spec>+<spec>` form.
405+
When `--use-bitmap-index` is specified with `--path-walk`, a successful
406+
bitmap traversal is used for object enumeration, with path-walk
407+
remaining as the fallback traversal when the bitmap cannot satisfy the
408+
request. The `--path-walk` option supports the `--filter=<spec>` forms
409+
`blob:none`, `blob:limit=<n>`, `tree:0`, `object:type=<type>`, and
410+
`sparse:<oid>`. These supported filter types can be combined with the
411+
`combine:<spec>+<spec>` form.
410412
411413
412414
DELTA ISLANDS

builtin/pack-objects.c

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,22 @@ static inline void oe_set_tree_depth(struct packing_data *pack,
27342734
pack->tree_depth[e - pack->objects] = tree_depth;
27352735
}
27362736

2737+
static void record_tree_depth(const struct object_id *oid, const char *name)
2738+
{
2739+
const char *p;
2740+
unsigned depth;
2741+
struct object_entry *ent;
2742+
2743+
/* the empty string is a root tree, which is depth 0 */
2744+
depth = *name ? 1 : 0;
2745+
for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
2746+
depth++;
2747+
2748+
ent = packlist_find(&to_pack, oid);
2749+
if (ent && depth > oe_tree_depth(&to_pack, ent))
2750+
oe_set_tree_depth(&to_pack, ent, depth);
2751+
}
2752+
27372753
/*
27382754
* Return the size of the object without doing any delta
27392755
* reconstruction (so non-deltas are true object sizes, but deltas
@@ -4392,20 +4408,8 @@ static void show_object(struct object *obj, const char *name,
43924408
add_preferred_base_object(name);
43934409
add_object_entry(&obj->oid, obj->type, name, 0);
43944410

4395-
if (use_delta_islands) {
4396-
const char *p;
4397-
unsigned depth;
4398-
struct object_entry *ent;
4399-
4400-
/* the empty string is a root tree, which is depth 0 */
4401-
depth = *name ? 1 : 0;
4402-
for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
4403-
depth++;
4404-
4405-
ent = packlist_find(&to_pack, &obj->oid);
4406-
if (ent && depth > oe_tree_depth(&to_pack, ent))
4407-
oe_set_tree_depth(&to_pack, ent, depth);
4408-
}
4411+
if (use_delta_islands)
4412+
record_tree_depth(&obj->oid, name);
44094413
}
44104414

44114415
static void show_object__ma_allow_any(struct object *obj, const char *name, void *data)
@@ -4749,6 +4753,31 @@ static int add_objects_by_path(const char *path,
47494753
continue;
47504754

47514755
add_object_entry(oid, type, path, exclude);
4756+
4757+
if (type == OBJ_COMMIT) {
4758+
struct commit *commit;
4759+
4760+
if (!write_bitmap_index && !use_delta_islands)
4761+
continue;
4762+
4763+
commit = lookup_commit(the_repository, oid);
4764+
if (!commit)
4765+
die(_("could not find commit %s"), oid_to_hex(oid));
4766+
if (write_bitmap_index)
4767+
index_commit_for_bitmap(commit);
4768+
/*
4769+
* Skip island propagation for boundary commits.
4770+
* The regular traversal's show_commit() is only
4771+
* called for interesting commits; matching that
4772+
* here keeps path-walk from doing extra work that
4773+
* would only be a no-op anyway (boundary commits
4774+
* are not in island_marks).
4775+
*/
4776+
if (use_delta_islands && !exclude)
4777+
propagate_island_marks(the_repository, commit);
4778+
} else if (type == OBJ_TREE && use_delta_islands) {
4779+
record_tree_depth(oid, path);
4780+
}
47524781
}
47534782

47544783
oe_end = to_pack.nr_objects;
@@ -4781,6 +4810,13 @@ static int get_object_list_path_walk(struct rev_info *revs)
47814810
info.path_fn = add_objects_by_path;
47824811
info.path_fn_data = &processed;
47834812

4813+
/*
4814+
* Path-walk needs boundary commits to discover thin-pack bases, but
4815+
* bitmap traversal does not understand the boundary state. Set it
4816+
* here so any prior bitmap attempt sees the usual non-boundary walk.
4817+
*/
4818+
revs->boundary = 1;
4819+
47844820
/*
47854821
* Allow the --[no-]sparse option to be interesting here, if only
47864822
* for testing purposes. Paths with no interesting objects will not
@@ -5204,8 +5240,6 @@ int cmd_pack_objects(int argc,
52045240
const char *option = NULL;
52055241
if (!path_walk_filter_compatible(&filter_options))
52065242
option = "--filter";
5207-
else if (use_delta_islands)
5208-
option = "--delta-islands";
52095243

52105244
if (option) {
52115245
warning(_("cannot use %s with %s"),
@@ -5214,9 +5248,7 @@ int cmd_pack_objects(int argc,
52145248
}
52155249
}
52165250
if (path_walk) {
5217-
strvec_push(&rp, "--boundary");
52185251
strvec_push(&rp, "--objects");
5219-
use_bitmap_index = 0;
52205252
} else if (thin) {
52215253
use_internal_rev_list = 1;
52225254
strvec_push(&rp, shallow

t/t5310-pack-bitmaps.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,42 @@ test_bitmap_cases
577577

578578
sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL
579579

580+
test_expect_success 'path-walk repack can write and use bitmap indexes' '
581+
test_when_finished "rm -rf path-walk-bitmap" &&
582+
git init path-walk-bitmap &&
583+
(
584+
cd path-walk-bitmap &&
585+
test_commit first &&
586+
test_commit second &&
587+
test_commit third &&
588+
589+
git repack -a -d -b --path-walk &&
590+
git rev-list --test-bitmap --use-bitmap-index HEAD &&
591+
592+
git rev-parse HEAD >in &&
593+
594+
git rev-list --objects --no-object-names HEAD >expect.raw &&
595+
sort expect.raw >expect &&
596+
597+
for reuse in true false
598+
do
599+
: >trace.txt &&
600+
601+
GIT_TRACE2_EVENT="$(pwd)/trace.txt" \
602+
git -c pack.allowPackReuse=$reuse pack-objects \
603+
--stdout --revs --path-walk --use-bitmap-index \
604+
<in >out.pack &&
605+
grep "\"category\":\"bitmap\",\"key\":\"bitmap/hits\"" trace.txt &&
606+
607+
git index-pack out.pack &&
608+
609+
list_packed_objects out.idx >actual.raw &&
610+
sort actual.raw >actual &&
611+
test_cmp expect actual || return 1
612+
done
613+
)
614+
'
615+
580616
test_expect_success 'incremental repack fails when bitmaps are requested' '
581617
test_commit more-1 &&
582618
test_must_fail git repack -d 2>err &&

t/t5320-delta-islands.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,35 @@ test_expect_success 'separate islands disallows delta' '
5353
! is_delta_base $two $one
5454
'
5555

56+
test_expect_success 'path-walk island repack respects islands' '
57+
GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-islands" \
58+
git -c "pack.island=refs/heads/(.*)" repack -adfi \
59+
--path-walk 2>err &&
60+
test_region pack-objects path-walk trace.path-walk-islands &&
61+
test_grep ! "cannot use --delta-islands with --path-walk" err &&
62+
! is_delta_base $one $two &&
63+
! is_delta_base $two $one
64+
'
65+
66+
test_expect_success 'path-walk island bitmap repack respects islands' '
67+
GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-island-bitmap" \
68+
git -c "pack.island=refs/heads/(.*)" repack -a -d -f -i -b \
69+
--path-walk 2>err &&
70+
test_region pack-objects path-walk trace.path-walk-island-bitmap &&
71+
test_path_is_file .git/objects/pack/*.bitmap &&
72+
git rev-list --test-bitmap --use-bitmap-index one &&
73+
test_grep ! "cannot use --delta-islands with --path-walk" err &&
74+
! is_delta_base $one $two &&
75+
! is_delta_base $two $one
76+
'
77+
78+
test_expect_success 'path-walk same island allows delta' '
79+
GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-same-island" \
80+
git -c "pack.island=refs/heads" repack -adfi --path-walk &&
81+
test_region pack-objects path-walk trace.path-walk-same-island &&
82+
is_delta_base $one $two
83+
'
84+
5685
test_expect_success 'same island allows delta' '
5786
git -c "pack.island=refs/heads" repack -adfi &&
5887
is_delta_base $one $two

0 commit comments

Comments
 (0)