Let's create a struct pack_idx_entry list with sorted sha1 which will
be useful later.  The offset sorted list is now a separate indirect
list.

Signed-off-by: Nicolas Pitre <n...@fluxnic.net>
---
 packv4-create.c | 72 +++++++++++++++++++++++++++++++++------------------------
 1 file changed, 42 insertions(+), 30 deletions(-)

diff --git a/packv4-create.c b/packv4-create.c
index 20d97a4..012129b 100644
--- a/packv4-create.c
+++ b/packv4-create.c
@@ -11,6 +11,7 @@
 #include "cache.h"
 #include "object.h"
 #include "tree-walk.h"
+#include "pack.h"
 
 struct data_entry {
        unsigned offset;
@@ -244,46 +245,53 @@ static void dict_dump(void)
        dump_dict_table(tree_path_table);
 }
 
-struct idx_entry
+static struct pack_idx_entry *get_packed_object_list(struct packed_git *p)
 {
-       off_t                offset;
-       const unsigned char *sha1;
-};
+       unsigned i, nr_objects = p->num_objects;
+       struct pack_idx_entry *objects;
+
+       objects = xmalloc((nr_objects + 1) * sizeof(*objects));
+       objects[nr_objects].offset = p->pack_size - 20;
+       for (i = 0; i < nr_objects; i++) {
+               hashcpy(objects[i].sha1, nth_packed_object_sha1(p, i));
+               objects[i].offset = nth_packed_object_offset(p, i);
+       }
+
+       return objects;
+}
 
 static int sort_by_offset(const void *e1, const void *e2)
 {
-       const struct idx_entry *entry1 = e1;
-       const struct idx_entry *entry2 = e2;
-       if (entry1->offset < entry2->offset)
+       const struct pack_idx_entry * const *entry1 = e1;
+       const struct pack_idx_entry * const *entry2 = e2;
+       if ((*entry1)->offset < (*entry2)->offset)
                return -1;
-       if (entry1->offset > entry2->offset)
+       if ((*entry1)->offset > (*entry2)->offset)
                return 1;
        return 0;
 }
 
-static struct idx_entry *get_packed_object_list(struct packed_git *p)
+static struct pack_idx_entry **sort_objs_by_offset(struct pack_idx_entry *list,
+                                                   unsigned nr_objects)
 {
-       uint32_t nr_objects, i;
-       struct idx_entry *objects;
+       unsigned i;
+       struct pack_idx_entry **sorted;
 
-       nr_objects = p->num_objects;
-       objects = xmalloc((nr_objects + 1) * sizeof(*objects));
-       objects[nr_objects].offset = p->index_size - 40;
-       for (i = 0; i < nr_objects; i++) {
-               objects[i].sha1 = nth_packed_object_sha1(p, i);
-               objects[i].offset = nth_packed_object_offset(p, i);
-       }
-       qsort(objects, nr_objects, sizeof(*objects), sort_by_offset);
+       sorted = xmalloc((nr_objects + 1) * sizeof(*sorted));
+       for (i = 0; i < nr_objects + 1; i++)
+               sorted[i] = &list[i];
+       qsort(sorted, nr_objects + 1, sizeof(*sorted), sort_by_offset);
 
-       return objects;
+       return sorted;
 }
 
 static int create_pack_dictionaries(struct packed_git *p,
-                                   struct idx_entry *objects)
+                                   struct pack_idx_entry **obj_list)
 {
        unsigned int i;
 
        for (i = 0; i < p->num_objects; i++) {
+               struct pack_idx_entry *obj = obj_list[i];
                void *data;
                enum object_type type;
                unsigned long size;
@@ -292,9 +300,9 @@ static int create_pack_dictionaries(struct packed_git *p,
 
                oi.typep = &type;
                oi.sizep = &size;
-               if (packed_object_info(p, objects[i].offset, &oi) < 0)
+               if (packed_object_info(p, obj->offset, &oi) < 0)
                        die("cannot get type of %s from %s",
-                           sha1_to_hex(objects[i].sha1), p->pack_name);
+                           sha1_to_hex(obj->sha1), p->pack_name);
 
                switch (type) {
                case OBJ_COMMIT:
@@ -306,16 +314,16 @@ static int create_pack_dictionaries(struct packed_git *p,
                default:
                        continue;
                }
-               data = unpack_entry(p, objects[i].offset, &type, &size);
+               data = unpack_entry(p, obj->offset, &type, &size);
                if (!data)
                        die("cannot unpack %s from %s",
-                           sha1_to_hex(objects[i].sha1), p->pack_name);
-               if (check_sha1_signature(objects[i].sha1, data, size, 
typename(type)))
+                           sha1_to_hex(obj->sha1), p->pack_name);
+               if (check_sha1_signature(obj->sha1, data, size, typename(type)))
                        die("packed %s from %s is corrupt",
-                           sha1_to_hex(objects[i].sha1), p->pack_name);
+                           sha1_to_hex(obj->sha1), p->pack_name);
                if (add_dict_entries(data, size) < 0)
                        die("can't process %s object %s",
-                               typename(type), sha1_to_hex(objects[i].sha1));
+                               typename(type), sha1_to_hex(obj->sha1));
                free(data);
        }
 
@@ -378,14 +386,18 @@ static struct packed_git *open_pack(const char *path)
 static void process_one_pack(char *src_pack)
 {
        struct packed_git *p;
-       struct idx_entry *objs;
+       struct pack_idx_entry *objs, **p_objs;
+       unsigned nr_objects;
 
        p = open_pack(src_pack);
        if (!p)
                die("unable to open source pack");
 
+       nr_objects = p->num_objects;
        objs = get_packed_object_list(p);
-       create_pack_dictionaries(p, objs);
+       p_objs = sort_objs_by_offset(objs, nr_objects);
+
+       create_pack_dictionaries(p, p_objs);
 }
 
 int main(int argc, char *argv[])
-- 
1.8.4.38.g317e65b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to