diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2012-01-09 10:59:06 +0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2012-01-09 12:46:42 -0800 |
commit | 522e6da7b7c6efe9f4855e74d71139e785552bf1 (patch) | |
tree | 1efdafe0ec2fe02c15dd3ff7b3c1a74c0f198768 | |
parent | 38edfb700ddd2939193d52b64f9358331525d755 (diff) | |
download | git-nd/index-pack-no-recurse.tar.gz |
index-pack: eliminate unlimited recursion in get_delta_base()nd/index-pack-no-recurse
Revert the order of delta applying so that by the time a delta is
applied, its base is either non-delta or already inflated.
get_delta_base() is still recursive, but because base's data is always
ready, the inner get_delta_base() call never has any chance to call
itself again.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | builtin/index-pack.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 38ff03a5cd..8c1f5d9979 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -519,10 +519,25 @@ static void *get_base_data(struct base_data *c) { if (!c->data) { struct object_entry *obj = c->obj; + struct base_data **delta = NULL; + int delta_nr = 0, delta_alloc = 0; - if (is_delta_type(obj->type)) { - void *base = get_base_data(c->base); - void *raw = get_data_from_pack(obj); + for (; is_delta_type(c->obj->type); c = c->base) { + ALLOC_GROW(delta, delta_nr + 1, delta_alloc); + delta[delta_nr++] = c; + } + if (!delta_nr) { + c->data = get_data_from_pack(obj); + c->size = obj->size; + base_cache_used += c->size; + prune_base_data(c); + } + for (; delta_nr > 0; delta_nr--) { + void *base, *raw; + c = delta[delta_nr - 1]; + obj = c->obj; + base = get_base_data(c->base); + raw = get_data_from_pack(obj); c->data = patch_delta( base, c->base->size, raw, obj->size, @@ -530,13 +545,10 @@ static void *get_base_data(struct base_data *c) free(raw); if (!c->data) bad_object(obj->idx.offset, "failed to apply delta"); - } else { - c->data = get_data_from_pack(obj); - c->size = obj->size; + base_cache_used += c->size; + prune_base_data(c); } - - base_cache_used += c->size; - prune_base_data(c); + free(delta); } return c->data; } |