Skip to content

Commit

Permalink
[PATCH] Find size of SHA1 object without inflating everything.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Junio C Hamano authored and Linus Torvalds committed Jun 2, 2005
1 parent 4a62b61 commit 65c2e0c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 5 deletions.
1 change: 1 addition & 0 deletions cache.h
Expand Up @@ -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);
Expand Down
11 changes: 6 additions & 5 deletions diff.c
Expand Up @@ -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;

Expand All @@ -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;
}
Expand Down
60 changes: 60 additions & 0 deletions sha1_file.c
Expand Up @@ -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;
Expand Down

0 comments on commit 65c2e0c

Please sign in to comment.