Whenever we make a struct base_data, immediately calculate its delta
children. This eliminates confusion as to when the
{ref,ofs}_{first,last} fields are initialized.

Signed-off-by: Jonathan Tan <jonathanta...@google.com>
---
 builtin/index-pack.c | 125 +++++++++++++++++++++----------------------
 1 file changed, 61 insertions(+), 64 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 35f7f9e52b..17997834ec 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -33,12 +33,15 @@ struct object_stat {
 };
 
 struct base_data {
+       /* Initialized by make_base(). */
        struct base_data *base;
        struct object_entry *obj;
-       void *data;
-       unsigned long size;
        int ref_first, ref_last;
        int ofs_first, ofs_last;
+
+       /* Not initialized by make_base(). */
+       void *data;
+       unsigned long size;
 };
 
 struct thread_local {
@@ -362,14 +365,6 @@ static void set_thread_data(struct thread_local *data)
                pthread_setspecific(key, data);
 }
 
-static struct base_data *alloc_base_data(void)
-{
-       struct base_data *base = xcalloc(1, sizeof(struct base_data));
-       base->ref_last = -1;
-       base->ofs_last = -1;
-       return base;
-}
-
 static void free_base_data(struct base_data *c)
 {
        if (c->data) {
@@ -406,19 +401,6 @@ static void prune_base_data(struct base_data 
*youngest_child)
        free(ancestry);
 }
 
-static void link_base_data(struct base_data *base, struct base_data *c)
-{
-       c->base = base;
-       if (c->data)
-               get_thread_data()->base_cache_used += c->size;
-       prune_base_data(c);
-}
-
-static void unlink_base_data(struct base_data *c)
-{
-       free_base_data(c);
-}
-
 static int is_delta_type(enum object_type type)
 {
        return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
@@ -928,10 +910,25 @@ static void *get_base_data(struct base_data *c)
        return c->data;
 }
 
-static void resolve_delta(struct object_entry *delta_obj,
-                         struct base_data *base, struct base_data *result)
+static struct base_data *make_base(struct object_entry *obj,
+                                  struct base_data *parent)
 {
-       void *base_data, *delta_data;
+       struct base_data *base = xcalloc(1, sizeof(struct base_data));
+       base->base = parent;
+       base->obj = obj;
+       find_ref_delta_children(&obj->idx.oid,
+                               &base->ref_first, &base->ref_last);
+       find_ofs_delta_children(obj->idx.offset,
+                               &base->ofs_first, &base->ofs_last);
+       return base;
+}
+
+static struct base_data *resolve_delta(struct object_entry *delta_obj,
+                                      struct base_data *base)
+{
+       void *base_data, *delta_data, *result_data;
+       struct base_data *result;
+       unsigned long result_size;
 
        if (show_stat) {
                int i = delta_obj - objects;
@@ -945,19 +942,31 @@ static void resolve_delta(struct object_entry *delta_obj,
        }
        delta_data = get_data_from_pack(delta_obj);
        base_data = get_base_data(base);
-       result->obj = delta_obj;
-       result->data = patch_delta(base_data, base->size,
-                                  delta_data, delta_obj->size, &result->size);
+       result_data = patch_delta(base_data, base->size,
+                                 delta_data, delta_obj->size, &result_size);
        free(delta_data);
-       if (!result->data)
+       if (!result_data)
                bad_object(delta_obj->idx.offset, _("failed to apply delta"));
-       hash_object_file(result->data, result->size,
+       hash_object_file(result_data, result_size,
                         type_name(delta_obj->real_type), &delta_obj->idx.oid);
-       sha1_object(result->data, NULL, result->size, delta_obj->real_type,
+       sha1_object(result_data, NULL, result_size, delta_obj->real_type,
                    &delta_obj->idx.oid);
+
+       result = make_base(delta_obj, base);
+       if (result->ref_last == -1 && result->ofs_last == -1) {
+               free(result_data);
+       } else {
+               result->data = result_data;
+               result->size = result_size;
+               get_thread_data()->base_cache_used += result->size;
+               prune_base_data(result);
+       }
+
        counter_lock();
        nr_resolved_deltas++;
        counter_unlock();
+
+       return result;
 }
 
 /*
@@ -983,30 +992,15 @@ static int compare_and_swap_type(signed char *type,
 static struct base_data *find_unresolved_deltas_1(struct base_data *base,
                                                  struct base_data *prev_base)
 {
-       if (base->ref_last == -1 && base->ofs_last == -1) {
-               find_ref_delta_children(&base->obj->idx.oid,
-                                       &base->ref_first, &base->ref_last);
-
-               find_ofs_delta_children(base->obj->idx.offset,
-                                       &base->ofs_first, &base->ofs_last);
-
-               if (base->ref_last == -1 && base->ofs_last == -1) {
-                       free(base->data);
-                       return NULL;
-               }
-
-               link_base_data(prev_base, base);
-       }
-
        if (base->ref_first <= base->ref_last) {
                struct object_entry *child = objects + 
ref_deltas[base->ref_first].obj_no;
-               struct base_data *result = alloc_base_data();
+               struct base_data *result;
 
                if (!compare_and_swap_type(&child->real_type, OBJ_REF_DELTA,
                                           base->obj->real_type))
                        BUG("child->real_type != OBJ_REF_DELTA");
 
-               resolve_delta(child, base, result);
+               result = resolve_delta(child, base);
                if (base->ref_first == base->ref_last && base->ofs_last == -1)
                        free_base_data(base);
 
@@ -1016,11 +1010,11 @@ static struct base_data 
*find_unresolved_deltas_1(struct base_data *base,
 
        if (base->ofs_first <= base->ofs_last) {
                struct object_entry *child = objects + 
ofs_deltas[base->ofs_first].obj_no;
-               struct base_data *result = alloc_base_data();
+               struct base_data *result;
 
                assert(child->real_type == OBJ_OFS_DELTA);
                child->real_type = base->obj->real_type;
-               resolve_delta(child, base, result);
+               result = resolve_delta(child, base);
                if (base->ofs_first == base->ofs_last)
                        free_base_data(base);
 
@@ -1028,7 +1022,7 @@ static struct base_data *find_unresolved_deltas_1(struct 
base_data *base,
                return result;
        }
 
-       unlink_base_data(base);
+       free_base_data(base);
        return NULL;
 }
 
@@ -1071,9 +1065,8 @@ static int compare_ref_delta_entry(const void *a, const 
void *b)
 
 static void resolve_base(struct object_entry *obj)
 {
-       struct base_data *base_obj = alloc_base_data();
-       base_obj->obj = obj;
-       base_obj->data = NULL;
+       struct base_data *base_obj = make_base(obj, NULL);
+
        find_unresolved_deltas(base_obj);
 }
 
@@ -1367,21 +1360,25 @@ static void fix_unresolved_deltas(struct hashfile *f)
        for (i = 0; i < nr_ref_deltas; i++) {
                struct ref_delta_entry *d = sorted_by_pos[i];
                enum object_type type;
-               struct base_data *base_obj = alloc_base_data();
+               struct base_data *base;
+               void *data;
+               unsigned long size;
+               struct object_entry *obj;
 
                if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
                        continue;
-               base_obj->data = read_object_file(&d->oid, &type,
-                                                 &base_obj->size);
-               if (!base_obj->data)
+               data = read_object_file(&d->oid, &type, &size);
+               if (!data)
                        continue;
 
-               if (check_object_signature(&d->oid, base_obj->data,
-                               base_obj->size, type_name(type)))
+               if (check_object_signature(&d->oid, data,
+                                          size, type_name(type)))
                        die(_("local object %s is corrupt"), 
oid_to_hex(&d->oid));
-               base_obj->obj = append_obj_to_pack(f, d->oid.hash,
-                                       base_obj->data, base_obj->size, type);
-               find_unresolved_deltas(base_obj);
+               obj = append_obj_to_pack(f, d->oid.hash, data, size, type);
+               base = make_base(obj, NULL);
+               base->data = data;
+               base->size = size;
+               find_unresolved_deltas(base);
                display_progress(progress, nr_resolved_deltas);
        }
        free(sorted_by_pos);
-- 
2.23.0.581.g78d2f28ef7-goog

Reply via email to