From c62266f37c677c1de7415ac6cf1e2eb6726590e1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 30 Jun 2005 17:13:07 -0700 Subject: [PATCH] [PATCH] Avoid unnecessarily inflating and interpreting delta This teaches packed_delta_info() that it only needs to look at the type of the base object to figure out both type and size of a deltified object. This saves quite a many calls to inflate() when dealing with a deep delta chain. Signed-off-by: Junio C Hamano Signed-off-by: Linus Torvalds --- cat-file.c | 3 +- sha1_file.c | 79 ++++++++++++++++++++++++++++------------------------- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/cat-file.c b/cat-file.c index 85a5d4cae..fa0bb722a 100644 --- a/cat-file.c +++ b/cat-file.c @@ -16,7 +16,8 @@ int main(int argc, char **argv) usage("git-cat-file [-t | -s | tagname] "); if (!strcmp("-t", argv[1]) || !strcmp("-s", argv[1])) { - if (!sha1_object_info(sha1, type, &size)) { + if (!sha1_object_info(sha1, type, + argv[1][1] == 's' ? &size : NULL)) { switch (argv[1][1]) { case 't': printf("%s\n", type); diff --git a/sha1_file.c b/sha1_file.c index 63cbdded8..3178fbf83 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -624,41 +624,49 @@ static int packed_delta_info(unsigned char *base_sha1, char *type, unsigned long *sizep) { - const unsigned char *data; - unsigned char delta_head[64]; - unsigned long result_size, base_size, verify_base_size; - z_stream stream; - int st; - if (left < 20) die("truncated pack file"); - if (sha1_object_info(base_sha1, type, &base_size)) - die("cannot get info for delta-pack base"); - - memset(&stream, 0, sizeof(stream)); - data = stream.next_in = base_sha1 + 20; - stream.avail_in = left - 20; - stream.next_out = delta_head; - stream.avail_out = sizeof(delta_head); + /* We choose to only get the type of the base object and + * ignore potentially corrupt pack file that expects the delta + * based on a base with a wrong size. This saves tons of + * inflate() calls. + */ - inflateInit(&stream); - st = inflate(&stream, Z_FINISH); - inflateEnd(&stream); - if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head)) - die("delta data unpack-initial failed"); + if (sha1_object_info(base_sha1, type, NULL)) + die("cannot get info for delta-pack base"); - /* Examine the initial part of the delta to figure out - * the result size. Verify the base size while we are at it. - */ - data = delta_head; - verify_base_size = get_delta_hdr_size(&data); - if (verify_base_size != base_size) - die("delta base size mismatch"); + if (sizep) { + const unsigned char *data; + unsigned char delta_head[64]; + unsigned long result_size; + z_stream stream; + int st; + + memset(&stream, 0, sizeof(stream)); + + data = stream.next_in = base_sha1 + 20; + stream.avail_in = left - 20; + stream.next_out = delta_head; + stream.avail_out = sizeof(delta_head); + + inflateInit(&stream); + st = inflate(&stream, Z_FINISH); + inflateEnd(&stream); + if ((st != Z_STREAM_END) && + stream.total_out != sizeof(delta_head)) + die("delta data unpack-initial failed"); + + /* Examine the initial part of the delta to figure out + * the result size. + */ + data = delta_head; + get_delta_hdr_size(&data); /* ignore base size */ - /* Read the result size */ - result_size = get_delta_hdr_size(&data); - *sizep = result_size; + /* Read the result size */ + result_size = get_delta_hdr_size(&data); + *sizep = result_size; + } return 0; } @@ -726,7 +734,8 @@ static int packed_object_info(struct pack_entry *entry, default: die("corrupted pack file"); } - *sizep = size; + if (sizep) + *sizep = size; unuse_packed_git(p); return 0; } @@ -915,12 +924,7 @@ int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep if (!find_pack_entry(sha1, &e)) return error("unable to find %s", sha1_to_hex(sha1)); - if (!packed_object_info(&e, type, sizep)) - return 0; - /* sheesh */ - map = unpack_entry(&e, type, sizep); - free(map); - return (map == NULL) ? 0 : -1; + return packed_object_info(&e, type, sizep); } if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) status = error("unable to unpack %s header", @@ -929,7 +933,8 @@ int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep status = error("unable to parse %s header", sha1_to_hex(sha1)); else { status = 0; - *sizep = size; + if (sizep) + *sizep = size; } inflateEnd(&stream); munmap(map, mapsize); -- 2.26.2