mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 06:20:56 +00:00
pack: simplify delta chain code
The switch makes the loop somewhat unwieldy. Let's assume it's fine and perform the check when we're accessing the data. This makes our code look a lot more like git's.
This commit is contained in:
parent
b2559f477a
commit
9dbd150f5f
100
src/pack.c
100
src/pack.c
@ -549,21 +549,38 @@ int git_packfile_unpack(
|
|||||||
|
|
||||||
/* the first one is the base, so we expand that one */
|
/* the first one is the base, so we expand that one */
|
||||||
elem = git_array_pop(chain);
|
elem = git_array_pop(chain);
|
||||||
|
base_type = elem->type;
|
||||||
if (elem->cached) {
|
if (elem->cached) {
|
||||||
cached = elem->cached_entry;
|
cached = elem->cached_entry;
|
||||||
memcpy(obj, &cached->raw, sizeof(git_rawobj));
|
memcpy(obj, &cached->raw, sizeof(git_rawobj));
|
||||||
base_type = obj->type;
|
|
||||||
} else {
|
|
||||||
curpos = elem->offset;
|
|
||||||
error = packfile_unpack_compressed(obj, p, &w_curs, &curpos, elem->size, elem->type);
|
|
||||||
git_mwindow_close(&w_curs);
|
|
||||||
base_type = elem->type;
|
|
||||||
free_base = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
switch (base_type) {
|
||||||
|
case GIT_OBJ_COMMIT:
|
||||||
|
case GIT_OBJ_TREE:
|
||||||
|
case GIT_OBJ_BLOB:
|
||||||
|
case GIT_OBJ_TAG:
|
||||||
|
if (!elem->cached) {
|
||||||
|
curpos = elem->offset;
|
||||||
|
error = packfile_unpack_compressed(obj, p, &w_curs, &curpos, elem->size, elem->type);
|
||||||
|
git_mwindow_close(&w_curs);
|
||||||
|
free_base = 1;
|
||||||
|
}
|
||||||
|
if (error < 0)
|
||||||
|
goto cleanup;
|
||||||
|
break;
|
||||||
|
case GIT_OBJ_OFS_DELTA:
|
||||||
|
case GIT_OBJ_REF_DELTA:
|
||||||
|
error = packfile_error("dependency chain ends in a delta");
|
||||||
|
goto cleanup;
|
||||||
|
default:
|
||||||
|
error = packfile_error("invalid packfile type in header");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finding the object we want as the base element is
|
* Finding the object we want as the base element is
|
||||||
* problematic, as we need to make sure we don't accidentally
|
* problematic, as we need to make sure we don't accidentally
|
||||||
@ -1229,7 +1246,7 @@ static int pack_dependency_chain(git_dependency_chain *chain_out, struct git_pac
|
|||||||
git_dependency_chain chain = GIT_ARRAY_INIT;
|
git_dependency_chain chain = GIT_ARRAY_INIT;
|
||||||
git_mwindow *w_curs = NULL;
|
git_mwindow *w_curs = NULL;
|
||||||
git_off_t curpos = obj_offset, base_offset;
|
git_off_t curpos = obj_offset, base_offset;
|
||||||
int error = 0, found_base = 0;
|
int error = 0;
|
||||||
size_t size;
|
size_t size;
|
||||||
git_otype type;
|
git_otype type;
|
||||||
|
|
||||||
@ -1237,7 +1254,7 @@ static int pack_dependency_chain(git_dependency_chain *chain_out, struct git_pac
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
git_array_init_to_size(chain, 64);
|
git_array_init_to_size(chain, 64);
|
||||||
while (!found_base && error == 0) {
|
while (true) {
|
||||||
struct pack_chain_elem *elem;
|
struct pack_chain_elem *elem;
|
||||||
git_pack_cache_entry *cached = NULL;
|
git_pack_cache_entry *cached = NULL;
|
||||||
|
|
||||||
@ -1248,6 +1265,16 @@ static int pack_dependency_chain(git_dependency_chain *chain_out, struct git_pac
|
|||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elem->base_key = obj_offset;
|
||||||
|
|
||||||
|
/* if we have a base cached, we can stop here instead */
|
||||||
|
if ((cached = cache_get(&p->bases, obj_offset)) != NULL) {
|
||||||
|
elem->cached_entry = cached;
|
||||||
|
elem->cached = 1;
|
||||||
|
elem->type = cached->raw.type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
|
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
|
||||||
git_mwindow_close(&w_curs);
|
git_mwindow_close(&w_curs);
|
||||||
|
|
||||||
@ -1260,51 +1287,26 @@ static int pack_dependency_chain(git_dependency_chain *chain_out, struct git_pac
|
|||||||
elem->type = type;
|
elem->type = type;
|
||||||
elem->base_key = obj_offset;
|
elem->base_key = obj_offset;
|
||||||
|
|
||||||
switch (type) {
|
if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA)
|
||||||
case GIT_OBJ_OFS_DELTA:
|
|
||||||
case GIT_OBJ_REF_DELTA:
|
|
||||||
/* if we have a base cached, we can stop here instead */
|
|
||||||
if ((cached = cache_get(&p->bases, obj_offset)) != NULL) {
|
|
||||||
elem->cached_entry = cached;
|
|
||||||
elem->cached = 1;
|
|
||||||
found_base = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
|
|
||||||
git_mwindow_close(&w_curs);
|
|
||||||
|
|
||||||
if (base_offset == 0)
|
|
||||||
return packfile_error("delta offset is zero");
|
|
||||||
if (base_offset < 0) { /* must actually be an error code */
|
|
||||||
error = (int)base_offset;
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we need to pass the pos *after* the delta-base bit */
|
|
||||||
elem->offset = curpos;
|
|
||||||
|
|
||||||
/* go through the loop again, but with the new object */
|
|
||||||
obj_offset = base_offset;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* one of these means we've found the final object in the chain */
|
base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
|
||||||
case GIT_OBJ_COMMIT:
|
git_mwindow_close(&w_curs);
|
||||||
case GIT_OBJ_TREE:
|
|
||||||
case GIT_OBJ_BLOB:
|
|
||||||
case GIT_OBJ_TAG:
|
|
||||||
found_base = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if (base_offset == 0) {
|
||||||
error = packfile_error("invalid packfile type in header");
|
error = packfile_error("delta offset is zero");
|
||||||
break;
|
goto on_error;
|
||||||
|
}
|
||||||
|
if (base_offset < 0) { /* must actually be an error code */
|
||||||
|
error = (int)base_offset;
|
||||||
|
goto on_error;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!found_base) {
|
/* we need to pass the pos *after* the delta-base bit */
|
||||||
git_array_clear(chain);
|
elem->offset = curpos;
|
||||||
return packfile_error("after dependency chain loop; cannot happen");
|
|
||||||
|
/* go through the loop again, but with the new object */
|
||||||
|
obj_offset = base_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
*chain_out = chain;
|
*chain_out = chain;
|
||||||
|
Loading…
Reference in New Issue
Block a user