Browse Source

[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 <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
maint
Junio C Hamano 20 years ago committed by Linus Torvalds
parent
commit
c62266f37c
  1. 3
      cat-file.c
  2. 39
      sha1_file.c

3
cat-file.c

@ -16,7 +16,8 @@ int main(int argc, char **argv) @@ -16,7 +16,8 @@ int main(int argc, char **argv)
usage("git-cat-file [-t | -s | tagname] <sha1>");

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);

39
sha1_file.c

@ -624,17 +624,25 @@ static int packed_delta_info(unsigned char *base_sha1, @@ -624,17 +624,25 @@ static int packed_delta_info(unsigned char *base_sha1,
char *type,
unsigned long *sizep)
{
if (left < 20)
die("truncated pack file");

/* 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.
*/

if (sha1_object_info(base_sha1, type, NULL))
die("cannot get info for delta-pack base");

if (sizep) {
const unsigned char *data;
unsigned char delta_head[64];
unsigned long result_size, base_size, verify_base_size;
unsigned long result_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;
@ -645,20 +653,20 @@ static int packed_delta_info(unsigned char *base_sha1, @@ -645,20 +653,20 @@ static int packed_delta_info(unsigned char *base_sha1,
inflateInit(&stream);
st = inflate(&stream, Z_FINISH);
inflateEnd(&stream);
if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head))
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. Verify the base size while we are at it.
* the result size.
*/
data = delta_head;
verify_base_size = get_delta_hdr_size(&data);
if (verify_base_size != base_size)
die("delta base size mismatch");
get_delta_hdr_size(&data); /* ignore base size */

/* Read the result size */
result_size = get_delta_hdr_size(&data);
*sizep = result_size;
}
return 0;
}

@ -726,6 +734,7 @@ static int packed_object_info(struct pack_entry *entry, @@ -726,6 +734,7 @@ static int packed_object_info(struct pack_entry *entry,
default:
die("corrupted pack file");
}
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 @@ -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,6 +933,7 @@ int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep @@ -929,6 +933,7 @@ 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;
if (sizep)
*sizep = size;
}
inflateEnd(&stream);

Loading…
Cancel
Save