Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/index-pack.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index c5a8f68..33722e1 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -24,6 +24,7 @@ struct object_entry { enum object_type real_type; unsigned delta_depth; int base_object_no; + int nr_bases; /* only valid for v4 trees */ }; union delta_base { @@ -489,6 +490,11 @@ static int is_delta_type(enum object_type type) return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA); } +static int is_delta_tree(const struct object_entry *obj) +{ + return obj->type == OBJ_PV4_TREE && obj->nr_bases > 0; +} + static void read_and_inflate(unsigned long offset, void *buf, unsigned long size, unsigned long wraparound, @@ -595,6 +601,20 @@ static void add_ofs_delta(struct object_entry *obj, nr_deltas++; } +static void add_tree_delta_base(struct object_entry *obj, + const unsigned char *base, + int delta_start) +{ + int i; + + for (i = delta_start; i < nr_deltas; i++) + if (!hashcmp(base, deltas[i].base.sha1)) + return; + + add_sha1_delta(obj, base); + obj->nr_bases++; +} + /* * v4 trees are actually kind of deltas and we don't do delta in the * first pass. This function only walks through a tree object to find @@ -608,12 +628,14 @@ static void *unpack_tree_v4(struct object_entry *obj, unsigned int nr = read_varint(); const unsigned char *last_base = NULL; struct strbuf sb = STRBUF_INIT; + int delta_start = nr_deltas; while (nr) { unsigned int copy_start_or_path = read_varint(); if (copy_start_or_path & 1) { /* copy_start */ unsigned int copy_count = read_varint(); if (copy_count & 1) { /* first delta */ last_base = read_sha1table_ref(); + add_tree_delta_base(obj, last_base, delta_start); } else if (!last_base) bad_object(offset, _("bad copy count index in unpack_tree_v4")); @@ -735,9 +757,15 @@ static void *unpack_raw_entry(struct object_entry *obj, switch (obj->type) { case OBJ_REF_DELTA: - add_sha1_delta(obj, fill_and_use(20)); + if (packv4) + add_sha1_delta(obj, read_sha1table_ref()); + else + add_sha1_delta(obj, fill_and_use(20)); break; case OBJ_OFS_DELTA: + if (packv4) + die(_("pack version 4 does not support ofs-delta type (offset %lu)"), + obj->idx.offset); offset = obj->idx.offset - read_varint(); if (offset <= 0 || offset >= obj->idx.offset) bad_object(obj->idx.offset, @@ -1293,8 +1321,7 @@ static void parse_pack_objects(unsigned char *sha1) for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; void *data = unpack_raw_entry(obj, obj->idx.sha1); - if (is_delta_type(obj->type) || - (!data && obj->type == OBJ_PV4_TREE)) { + if (is_delta_type(obj->type) || is_delta_tree(obj)) { /* delay sha1_object() until second pass */ } else if (!data) { /* large blobs, check later */ -- 1.8.2.83.gc99314b -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html