mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-21 18:03:54 +00:00
pack: add git_packfile_resolve_header
To paraphrase @peff: You can get both size and type from a packed object reasonably cheaply. If you have: * An object that is not a delta; both type and size are available in the packfile header. * An object that is a delta. The packfile type will be OBJ_*_DELTA, and you have to resolve back to the base to find the real type. That means potentially a lot of packfile index lookups, but each one is relatively cheap. For the size, you inflate the first few bytes of the delta, whose header will tell you the resulting size of applying the delta to the base. For simplicity, we just decompress the whole delta for now.
This commit is contained in:
parent
d1b6ea8ad1
commit
44f9f54797
50
src/pack.c
50
src/pack.c
@ -277,6 +277,56 @@ int git_packfile_unpack_header(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_packfile_resolve_header(
|
||||
size_t *size_p,
|
||||
git_otype *type_p,
|
||||
struct git_pack_file *p,
|
||||
git_off_t offset)
|
||||
{
|
||||
git_mwindow *w_curs = NULL;
|
||||
git_off_t curpos = offset;
|
||||
size_t size;
|
||||
git_otype type;
|
||||
git_off_t base_offset;
|
||||
int error;
|
||||
|
||||
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
|
||||
git_mwindow_close(&w_curs);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
|
||||
size_t base_size;
|
||||
git_rawobj delta;
|
||||
base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
|
||||
git_mwindow_close(&w_curs);
|
||||
error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, size, type);
|
||||
git_mwindow_close(&w_curs);
|
||||
if (error < 0)
|
||||
return error;
|
||||
error = git__delta_read_header(delta.data, delta.len, &base_size, size_p);
|
||||
git__free(delta.data);
|
||||
if (error < 0)
|
||||
return error;
|
||||
} else
|
||||
*size_p = size;
|
||||
|
||||
while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
|
||||
curpos = base_offset;
|
||||
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
|
||||
git_mwindow_close(&w_curs);
|
||||
if (error < 0)
|
||||
return error;
|
||||
if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA)
|
||||
break;
|
||||
base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset);
|
||||
git_mwindow_close(&w_curs);
|
||||
}
|
||||
*type_p = type;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int packfile_unpack_delta(
|
||||
git_rawobj *obj,
|
||||
struct git_pack_file *p,
|
||||
|
@ -83,6 +83,12 @@ int git_packfile_unpack_header(
|
||||
git_mwindow **w_curs,
|
||||
git_off_t *curpos);
|
||||
|
||||
int git_packfile_resolve_header(
|
||||
size_t *size_p,
|
||||
git_otype *type_p,
|
||||
struct git_pack_file *p,
|
||||
git_off_t offset);
|
||||
|
||||
int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, git_off_t *obj_offset);
|
||||
int packfile_unpack_compressed(
|
||||
git_rawobj *obj,
|
||||
|
Loading…
Reference in New Issue
Block a user