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>maint
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;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define POI_STACK_PREALLOC 64
|
#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,
|
static int packed_object_info(struct packed_git *p, off_t obj_offset,
|
||||||
unsigned long *sizep, int *rtype,
|
unsigned long *sizep, int *rtype,
|
||||||
unsigned long *disk_sizep)
|
unsigned long *disk_sizep)
|
||||||
|
@ -1721,9 +1787,6 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
off_t curpos = obj_offset;
|
off_t curpos = obj_offset;
|
||||||
enum object_type type;
|
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);
|
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;
|
*disk_sizep = revidx[1].offset - obj_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
|
type = packed_to_object_type(p, obj_offset, type, &w_curs, curpos);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (poi_stack != small_poi_stack)
|
|
||||||
free(poi_stack);
|
|
||||||
unuse_pack(&w_curs);
|
unuse_pack(&w_curs);
|
||||||
return type;
|
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,
|
static void *unpack_compressed_entry(struct packed_git *p,
|
||||||
|
|
Loading…
Reference in New Issue