consolidate two copies of new style object header parsing code.
Also while we are at it, remove redundant typename[] array from unpack_sha1_header. The only reason it is different from the type_names[] array in object.c module is that this code cares about the subset of object types that are valid in a loose object, so prepare a separate array of boolean that tells us which types are valid, and share the name translation with the others. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
501524e938
commit
ad1ed5ee89
85
sha1_file.c
85
sha1_file.c
@ -711,17 +711,39 @@ int legacy_loose_object(unsigned char *map)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep)
|
||||||
|
{
|
||||||
|
unsigned shift;
|
||||||
|
unsigned char c;
|
||||||
|
unsigned long size;
|
||||||
|
unsigned long used = 0;
|
||||||
|
|
||||||
|
c = buf[used++];
|
||||||
|
*type = (c >> 4) & 7;
|
||||||
|
size = c & 15;
|
||||||
|
shift = 4;
|
||||||
|
while (c & 0x80) {
|
||||||
|
if (len <= used)
|
||||||
|
return 0;
|
||||||
|
if (sizeof(long) * 8 <= shift)
|
||||||
|
return 0;
|
||||||
|
c = buf[used++];
|
||||||
|
size += (c & 0x7f) << shift;
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
*sizep = size;
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
|
static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
|
||||||
{
|
{
|
||||||
unsigned char c;
|
unsigned long size, used;
|
||||||
unsigned int bits;
|
static const char valid_loose_object_type[8] = {
|
||||||
unsigned long size;
|
0, /* OBJ_EXT */
|
||||||
static const char *typename[8] = {
|
1, 1, 1, 1, /* "commit", "tree", "blob", "tag" */
|
||||||
NULL, /* OBJ_EXT */
|
0, /* "delta" and others are invalid in a loose object */
|
||||||
"commit", "tree", "blob", "tag",
|
|
||||||
NULL, NULL, NULL
|
|
||||||
};
|
};
|
||||||
const char *type;
|
enum object_type type;
|
||||||
|
|
||||||
/* Get the data stream */
|
/* Get the data stream */
|
||||||
memset(stream, 0, sizeof(*stream));
|
memset(stream, 0, sizeof(*stream));
|
||||||
@ -735,22 +757,11 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
|
|||||||
return inflate(stream, 0);
|
return inflate(stream, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *map++;
|
used = unpack_object_header_gently(map, mapsize, &type, &size);
|
||||||
mapsize--;
|
if (!used || !valid_loose_object_type[type])
|
||||||
type = typename[(c >> 4) & 7];
|
|
||||||
if (!type)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
map += used;
|
||||||
bits = 4;
|
mapsize -= used;
|
||||||
size = c & 0xf;
|
|
||||||
while ((c & 0x80)) {
|
|
||||||
if (bits >= 8*sizeof(long))
|
|
||||||
return -1;
|
|
||||||
c = *map++;
|
|
||||||
size += (c & 0x7f) << bits;
|
|
||||||
bits += 7;
|
|
||||||
mapsize--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up the stream for the rest.. */
|
/* Set up the stream for the rest.. */
|
||||||
stream->next_in = map;
|
stream->next_in = map;
|
||||||
@ -758,7 +769,8 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
|
|||||||
inflateInit(stream);
|
inflateInit(stream);
|
||||||
|
|
||||||
/* And generate the fake traditional header */
|
/* And generate the fake traditional header */
|
||||||
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", type, size);
|
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
|
||||||
|
type_names[type], size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -916,25 +928,18 @@ static int packed_delta_info(unsigned char *base_sha1,
|
|||||||
static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
|
static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
|
||||||
enum object_type *type, unsigned long *sizep)
|
enum object_type *type, unsigned long *sizep)
|
||||||
{
|
{
|
||||||
unsigned shift;
|
unsigned long used;
|
||||||
unsigned char c;
|
|
||||||
unsigned long size;
|
|
||||||
|
|
||||||
if (offset >= p->pack_size)
|
if (p->pack_size <= offset)
|
||||||
die("object offset outside of pack file");
|
die("object offset outside of pack file");
|
||||||
c = *((unsigned char *)p->pack_base + offset++);
|
|
||||||
*type = (c >> 4) & 7;
|
used = unpack_object_header_gently((unsigned char *)p->pack_base +
|
||||||
size = c & 15;
|
offset,
|
||||||
shift = 4;
|
p->pack_size - offset, type, sizep);
|
||||||
while (c & 0x80) {
|
if (!used)
|
||||||
if (offset >= p->pack_size)
|
|
||||||
die("object offset outside of pack file");
|
die("object offset outside of pack file");
|
||||||
c = *((unsigned char *)p->pack_base + offset++);
|
|
||||||
size += (c & 0x7f) << shift;
|
return offset + used;
|
||||||
shift += 7;
|
|
||||||
}
|
|
||||||
*sizep = size;
|
|
||||||
return offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,
|
int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,
|
||||||
|
Loading…
Reference in New Issue
Block a user