{"thread":{"id":"1063","subject":"[PATCH] Avoid unnecessarily inflating and interpreting delta","startedAt":"2005-07-01T00:13:07Z","lastAt":"2005-07-01T00:13:07Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"5501","messageId":"7vwtobz8mk.fsf@assigned-by-dhcp.cox.net","threadId":"1063","inReplyTo":null,"subject":"[PATCH] Avoid unnecessarily inflating and interpreting delta","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-01T00:13:07Z","receivedAt":"2005-07-01T00:13:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This teaches packed_delta_info() that it only needs to look at\nthe type of the base object to figure out both type and size of\na deltified object.  This saves quite a many calls to inflate()\nwhen dealing with a deep delta chain.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n cat-file.c  |    3 ++\n sha1_file.c |   77 +++++++++++++++++++++++++++++++----------------------------\n 2 files changed, 43 insertions(+), 37 deletions(-)\n\nf0792cd64bd42cde6706dc2c039e7b6901547169\ndiff --git a/cat-file.c b/cat-file.c\n--- a/cat-file.c\n+++ b/cat-file.c\n@@ -16,7 +16,8 @@ int main(int argc, char **argv)\n \t\tusage(\"git-cat-file [-t | -s | tagname] <sha1>\");\n \n \tif (!strcmp(\"-t\", argv[1]) || !strcmp(\"-s\", argv[1])) {\n-\t\tif (!sha1_object_info(sha1, type, &size)) {\n+\t\tif (!sha1_object_info(sha1, type,\n+\t\t\t\t      argv[1][1] == 's' ? &size : NULL)) {\n \t\t\tswitch (argv[1][1]) {\n \t\t\tcase 't':\n \t\t\t\tprintf(\"%s\\n\", type);\ndiff --git a/sha1_file.c b/sha1_file.c\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -624,41 +624,49 @@ static int packed_delta_info(unsigned ch\n \t\t\t     char *type,\n \t\t\t     unsigned long *sizep)\n {\n-\tconst unsigned char *data;\n-\tunsigned char delta_head[64];\n-\tunsigned long result_size, base_size, verify_base_size;\n-\tz_stream stream;\n-\tint st;\n-\n \tif (left < 20)\n \t\tdie(\"truncated pack file\");\n-\tif (sha1_object_info(base_sha1, type, &base_size))\n-\t\tdie(\"cannot get info for delta-pack base\");\n \n-\tmemset(&stream, 0, sizeof(stream));\n+\t/* We choose to only get the type of the base object and\n+\t * ignore potentially corrupt pack file that expects the delta\n+\t * based on a base with a wrong size.  This saves tons of\n+\t * inflate() calls.\n+\t */\n \n-\tdata = stream.next_in = base_sha1 + 20;\n-\tstream.avail_in = left - 20;\n-\tstream.next_out = delta_head;\n-\tstream.avail_out = sizeof(delta_head);\n+\tif (sha1_object_info(base_sha1, type, NULL))\n+\t\tdie(\"cannot get info for delta-pack base\");\n \n-\tinflateInit(&stream);\n-\tst = inflate(&stream, Z_FINISH);\n-\tinflateEnd(&stream);\n-\tif ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head))\n-\t\tdie(\"delta data unpack-initial failed\");\n+\tif (sizep) {\n+\t\tconst unsigned char *data;\n+\t\tunsigned char delta_head[64];\n+\t\tunsigned long result_size;\n+\t\tz_stream stream;\n+\t\tint st;\n+\n+\t\tmemset(&stream, 0, sizeof(stream));\n+\n+\t\tdata = stream.next_in = base_sha1 + 20;\n+\t\tstream.avail_in = left - 20;\n+\t\tstream.next_out = delta_head;\n+\t\tstream.avail_out = sizeof(delta_head);\n+\n+\t\tinflateInit(&stream);\n+\t\tst = inflate(&stream, Z_FINISH);\n+\t\tinflateEnd(&stream);\n+\t\tif ((st != Z_STREAM_END) &&\n+\t\t    stream.total_out != sizeof(delta_head))\n+\t\t\tdie(\"delta data unpack-initial failed\");\n \n-\t/* Examine the initial part of the delta to figure out\n-\t * the result size.  Verify the base size while we are at it.\n-\t */\n-\tdata = delta_head;\n-\tverify_base_size = get_delta_hdr_size(&data);\n-\tif (verify_base_size != base_size)\n-\t\tdie(\"delta base size mismatch\");\n+\t\t/* Examine the initial part of the delta to figure out\n+\t\t * the result size.\n+\t\t */\n+\t\tdata = delta_head;\n+\t\tget_delta_hdr_size(&data); /* ignore base size */\n \n-\t/* Read the result size */\n-\tresult_size = get_delta_hdr_size(&data);\n-\t*sizep = result_size;\n+\t\t/* Read the result size */\n+\t\tresult_size = get_delta_hdr_size(&data);\n+\t\t*sizep = result_size;\n+\t}\n \treturn 0;\n }\n \n@@ -726,7 +734,8 @@ static int packed_object_info(struct pac\n \tdefault:\n \t\tdie(\"corrupted pack file\");\n \t}\n-\t*sizep = size;\n+\tif (sizep)\n+\t\t*sizep = size;\n \tunuse_packed_git(p);\n \treturn 0;\n }\n@@ -915,12 +924,7 @@ int sha1_object_info(const unsigned char\n \n \t\tif (!find_pack_entry(sha1, &e))\n \t\t\treturn error(\"unable to find %s\", sha1_to_hex(sha1));\n-\t\tif (!packed_object_info(&e, type, sizep))\n-\t\t\treturn 0;\n-\t\t/* sheesh */\n-\t\tmap = unpack_entry(&e, type, sizep);\n-\t\tfree(map);\n-\t\treturn (map == NULL) ? 0 : -1;\n+\t\treturn packed_object_info(&e, type, sizep);\n \t}\n \tif (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)\n \t\tstatus = error(\"unable to unpack %s header\",\n@@ -929,7 +933,8 @@ int sha1_object_info(const unsigned char\n \t\tstatus = error(\"unable to parse %s header\", sha1_to_hex(sha1));\n \telse {\n \t\tstatus = 0;\n-\t\t*sizep = size;\n+\t\tif (sizep)\n+\t\t\t*sizep = size;\n \t}\n \tinflateEnd(&stream);\n \tmunmap(map, mapsize);\n------------\n"}]}