[PATCH] Find size of SHA1 object without inflating everything.

This adds sha1_file_size() helper function and uses it in the
rename/copy similarity estimator.  The helper function handles
deltified object as well.

Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Junio C Hamano 2005-06-02 15:20:54 -07:00 committed by Linus Torvalds
parent 4a62b61939
commit 65c2e0c349
3 changed files with 67 additions and 5 deletions

View File

@ -154,6 +154,7 @@ extern void * map_sha1_file(const unsigned char *sha1, unsigned long *size);
extern int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size);
extern int parse_sha1_header(char *hdr, char *type, unsigned long *sizep);
extern int sha1_delta_base(const unsigned char *, unsigned char *);
extern int sha1_file_size(const unsigned char *, unsigned long *);
extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);
extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);

11
diff.c
View File

@ -333,7 +333,6 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
close(fd);
}
else {
/* We cannot do size only for SHA1 blobs */
char type[20];
struct sha1_size_cache *e;
@ -343,11 +342,13 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
s->size = e->size;
return 0;
}
if (!sha1_file_size(s->sha1, &s->size))
locate_size_cache(s->sha1, s->size);
}
else {
s->data = read_sha1_file(s->sha1, type, &s->size);
s->should_free = 1;
}
s->data = read_sha1_file(s->sha1, type, &s->size);
s->should_free = 1;
if (s->data && size_only)
locate_size_cache(s->sha1, s->size);
}
return 0;
}

View File

@ -432,6 +432,66 @@ int sha1_delta_base(const unsigned char *sha1, unsigned char *base_sha1)
return ret;
}
int sha1_file_size(const unsigned char *sha1, unsigned long *sizep)
{
int ret, status;
unsigned long mapsize, size;
void *map;
z_stream stream;
char hdr[64], type[20];
const unsigned char *data;
unsigned char cmd;
int i;
map = map_sha1_file(sha1, &mapsize);
if (!map)
return -1;
ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));
status = -1;
if (ret < Z_OK || parse_sha1_header(hdr, type, &size) < 0)
goto out;
if (strcmp(type, "delta")) {
*sizep = size;
status = 0;
goto out;
}
/* We are dealing with a delta object. Inflated, the first
* 20 bytes hold the base object SHA1, and delta data follows
* immediately after it.
*
* The initial part of the delta starts at delta_data_head +
* 20. Borrow code from patch-delta to read the result size.
*/
data = hdr + strlen(hdr) + 1 + 20;
/* Skip over the source size; we are not interested in
* it and we cannot verify it because we do not want
* to read the base object.
*/
cmd = *data++;
while (cmd) {
if (cmd & 1)
data++;
cmd >>= 1;
}
/* Read the result size */
size = i = 0;
cmd = *data++;
while (cmd) {
if (cmd & 1)
size |= *data++ << i;
i += 8;
cmd >>= 1;
}
*sizep = size;
status = 0;
out:
inflateEnd(&stream);
munmap(map, mapsize);
return status;
}
void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
{
unsigned long mapsize;