packed_object_info: hoist delta type resolution to helper
To calculate the type of a packed object, we must walk down its delta chain until we hit a true base object with a real type. Most of the code in packed_object_info is for handling this case. Let's hoist it out into a separate helper function, which will make it easier to make the type-lookup optional in the future (and keep our indentation level sane). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
052fe5eaca
commit
90191d37ab
123
sha1_file.c
123
sha1_file.c
@ -1710,9 +1710,75 @@ static int retry_bad_packed_offset(struct packed_git *p, off_t obj_offset)
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
#define POI_STACK_PREALLOC 64
|
||||
|
||||
static enum object_type packed_to_object_type(struct packed_git *p,
|
||||
off_t obj_offset,
|
||||
enum object_type type,
|
||||
struct pack_window **w_curs,
|
||||
off_t curpos)
|
||||
{
|
||||
off_t small_poi_stack[POI_STACK_PREALLOC];
|
||||
off_t *poi_stack = small_poi_stack;
|
||||
int poi_stack_nr = 0, poi_stack_alloc = POI_STACK_PREALLOC;
|
||||
|
||||
while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
|
||||
off_t base_offset;
|
||||
unsigned long size;
|
||||
/* Push the object we're going to leave behind */
|
||||
if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack) {
|
||||
poi_stack_alloc = alloc_nr(poi_stack_nr);
|
||||
poi_stack = xmalloc(sizeof(off_t)*poi_stack_alloc);
|
||||
memcpy(poi_stack, small_poi_stack, sizeof(off_t)*poi_stack_nr);
|
||||
} else {
|
||||
ALLOC_GROW(poi_stack, poi_stack_nr+1, poi_stack_alloc);
|
||||
}
|
||||
poi_stack[poi_stack_nr++] = obj_offset;
|
||||
/* If parsing the base offset fails, just unwind */
|
||||
base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset);
|
||||
if (!base_offset)
|
||||
goto unwind;
|
||||
curpos = obj_offset = base_offset;
|
||||
type = unpack_object_header(p, w_curs, &curpos, &size);
|
||||
if (type <= OBJ_NONE) {
|
||||
/* If getting the base itself fails, we first
|
||||
* retry the base, otherwise unwind */
|
||||
type = retry_bad_packed_offset(p, base_offset);
|
||||
if (type > OBJ_NONE)
|
||||
goto out;
|
||||
goto unwind;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case OBJ_BAD:
|
||||
case OBJ_COMMIT:
|
||||
case OBJ_TREE:
|
||||
case OBJ_BLOB:
|
||||
case OBJ_TAG:
|
||||
break;
|
||||
default:
|
||||
error("unknown object type %i at offset %"PRIuMAX" in %s",
|
||||
type, (uintmax_t)obj_offset, p->pack_name);
|
||||
type = OBJ_BAD;
|
||||
}
|
||||
|
||||
out:
|
||||
if (poi_stack != small_poi_stack)
|
||||
free(poi_stack);
|
||||
return type;
|
||||
|
||||
unwind:
|
||||
while (poi_stack_nr) {
|
||||
obj_offset = poi_stack[--poi_stack_nr];
|
||||
type = retry_bad_packed_offset(p, obj_offset);
|
||||
if (type > OBJ_NONE)
|
||||
goto out;
|
||||
}
|
||||
type = OBJ_BAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int packed_object_info(struct packed_git *p, off_t obj_offset,
|
||||
unsigned long *sizep, int *rtype,
|
||||
unsigned long *disk_sizep)
|
||||
@ -1721,9 +1787,6 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
|
||||
unsigned long size;
|
||||
off_t curpos = obj_offset;
|
||||
enum object_type type;
|
||||
off_t small_poi_stack[POI_STACK_PREALLOC];
|
||||
off_t *poi_stack = small_poi_stack;
|
||||
int poi_stack_nr = 0, poi_stack_alloc = POI_STACK_PREALLOC;
|
||||
|
||||
type = unpack_object_header(p, &w_curs, &curpos, &size);
|
||||
|
||||
@ -1754,61 +1817,11 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
|
||||
*disk_sizep = revidx[1].offset - obj_offset;
|
||||
}
|
||||
|
||||
while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
|
||||
off_t base_offset;
|
||||
/* Push the object we're going to leave behind */
|
||||
if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack) {
|
||||
poi_stack_alloc = alloc_nr(poi_stack_nr);
|
||||
poi_stack = xmalloc(sizeof(off_t)*poi_stack_alloc);
|
||||
memcpy(poi_stack, small_poi_stack, sizeof(off_t)*poi_stack_nr);
|
||||
} else {
|
||||
ALLOC_GROW(poi_stack, poi_stack_nr+1, poi_stack_alloc);
|
||||
}
|
||||
poi_stack[poi_stack_nr++] = obj_offset;
|
||||
/* If parsing the base offset fails, just unwind */
|
||||
base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
|
||||
if (!base_offset)
|
||||
goto unwind;
|
||||
curpos = obj_offset = base_offset;
|
||||
type = unpack_object_header(p, &w_curs, &curpos, &size);
|
||||
if (type <= OBJ_NONE) {
|
||||
/* If getting the base itself fails, we first
|
||||
* retry the base, otherwise unwind */
|
||||
type = retry_bad_packed_offset(p, base_offset);
|
||||
if (type > OBJ_NONE)
|
||||
goto out;
|
||||
goto unwind;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case OBJ_BAD:
|
||||
case OBJ_COMMIT:
|
||||
case OBJ_TREE:
|
||||
case OBJ_BLOB:
|
||||
case OBJ_TAG:
|
||||
break;
|
||||
default:
|
||||
error("unknown object type %i at offset %"PRIuMAX" in %s",
|
||||
type, (uintmax_t)obj_offset, p->pack_name);
|
||||
type = OBJ_BAD;
|
||||
}
|
||||
type = packed_to_object_type(p, obj_offset, type, &w_curs, curpos);
|
||||
|
||||
out:
|
||||
if (poi_stack != small_poi_stack)
|
||||
free(poi_stack);
|
||||
unuse_pack(&w_curs);
|
||||
return type;
|
||||
|
||||
unwind:
|
||||
while (poi_stack_nr) {
|
||||
obj_offset = poi_stack[--poi_stack_nr];
|
||||
type = retry_bad_packed_offset(p, obj_offset);
|
||||
if (type > OBJ_NONE)
|
||||
goto out;
|
||||
}
|
||||
type = OBJ_BAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void *unpack_compressed_entry(struct packed_git *p,
|
||||
|
Loading…
Reference in New Issue
Block a user