[PATCH 1/4] t/helper: teach pack-deltas to list delta entries
From: Taylor Blau <hidden>
Date: 2026-07-13 01:11:56
Subsystem:
the rest · Maintainer:
Linus Torvalds
In the following commit(s), some tests will need to distinguish between `REF_DELTA`s and `OFS_DELTA`s to exercise a new '--no-ref-delta' option for 'pack-objects'. Existing tools report delta relationships, but not how their bases are represented in the pack. Teach 'test-tool pack-deltas' a '--list-deltas' mode. For each delta entry, print the object ID, its REF_DELTA or OFS_DELTA type, and the base object ID or pack offset, respectively. This lets tests inspect pack headers without open-coding a parser. Signed-off-by: Taylor Blau <redacted> --- t/helper/test-pack-deltas.c | 69 +++++++++++++++++++++++++++++++++++++ t/t5300-pack-object.sh | 8 +++-- 2 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/t/helper/test-pack-deltas.c b/t/helper/test-pack-deltas.c
index 840797cf0d..4ba6fe2dd3 100644
--- a/t/helper/test-pack-deltas.c
+++ b/t/helper/test-pack-deltas.c@@ -7,6 +7,7 @@ #include "hash.h" #include "hex.h" #include "pack.h" +#include "packfile.h" #include "pack-objects.h" #include "parse-options.h" #include "setup.h"
@@ -15,6 +16,7 @@ static const char *usage_str[] = { "test-tool pack-deltas --num-objects <num-objects>", + "test-tool pack-deltas --list-deltas <pack>.idx", NULL };
@@ -80,19 +82,86 @@ static void write_ref_delta(struct hashfile *f, free(delta_buf); } +static int list_delta(const struct object_id *oid, + struct packed_git *p, + uint32_t pos, + void *_w_curs) +{ + struct pack_window **w_curs = _w_curs; + off_t obj_offset = nth_packed_object_offset(p, pos); + off_t cur = obj_offset; + size_t size; + enum object_type type = unpack_object_header(p, w_curs, &cur, + &size); + + if (type < 0) + die("unable to parse object at position %"PRIu32, pos); + if (type != OBJ_REF_DELTA && type != OBJ_OFS_DELTA) + return 0; + + if (type == OBJ_REF_DELTA) { + struct object_id base_oid; + const unsigned char *base = use_pack(p, w_curs, cur, + NULL); + + oidread(&base_oid, base, p->repo->hash_algo); + printf("%s REF_DELTA %s\n", oid_to_hex(oid), + oid_to_hex(&base_oid)); + } else { + off_t base_offset = get_delta_base(p, w_curs, &cur, + type, obj_offset); + + if (!base_offset) + die("unable to read base of object %s", oid_to_hex(oid)); + printf("%s OFS_DELTA %"PRIuMAX"\n", oid_to_hex(oid), + (uintmax_t)base_offset); + } + + return 0; +} + +static void list_deltas(const char *idx_name) +{ + struct packed_git *p; + struct pack_window *w_curs = NULL; + + p = add_packed_git(the_repository, idx_name, strlen(idx_name), 1); + if (!p || open_pack_index(p)) + die("unable to open pack index %s", idx_name); + + if (for_each_object_in_pack(p, list_delta, &w_curs, + ODB_FOR_EACH_OBJECT_PACK_ORDER)) + die("unable to iterate over objects in %s", idx_name); + + unuse_pack(&w_curs); + close_pack(p); + free(p); +} + int cmd__pack_deltas(int argc, const char **argv) { int num_objects = -1; + int list_deltas_mode = 0; struct hashfile *f; struct strbuf line = STRBUF_INIT; struct option options[] = { OPT_INTEGER('n', "num-objects", &num_objects, N_("the number of objects to write")), + OPT_BOOL(0, "list-deltas", &list_deltas_mode, + N_("list REF_DELTA and OFS_DELTA entries")), OPT_END() }; argc = parse_options(argc, argv, NULL, options, usage_str, 0); + if (list_deltas_mode) { + if (argc != 1 || num_objects >= 0) + usage_with_options(usage_str, options); + setup_git_directory(the_repository); + list_deltas(argv[0]); + return 0; + } + if (argc || num_objects < 0) usage_with_options(usage_str, options);
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 73445782e7..4bee490ff6 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh@@ -190,7 +190,9 @@ test_expect_success 'unpack without delta (core.fsyncmethod=batch)' ' test_expect_success 'pack with REF_DELTA' ' packname_2=$(git pack-objects --progress test-2 <obj-list 2>stderr) && - check_deltas stderr -gt 0 + check_deltas stderr -gt 0 && + test-tool pack-deltas --list-deltas test-2-$packname_2.idx >deltas && + test_grep " REF_DELTA " deltas ' test_expect_success 'unpack with REF_DELTA' '
@@ -204,7 +206,9 @@ test_expect_success 'unpack with REF_DELTA (core.fsyncmethod=batch)' ' test_expect_success 'pack with OFS_DELTA' ' packname_3=$(git pack-objects --progress --delta-base-offset test-3 \ <obj-list 2>stderr) && - check_deltas stderr -gt 0 + check_deltas stderr -gt 0 && + test-tool pack-deltas --list-deltas test-3-$packname_3.idx >deltas && + test_grep " OFS_DELTA " deltas ' test_expect_success 'unpack with OFS_DELTA' '
--
2.55.0