]> git.proxmox.com Git - libgit2.git/commitdiff
pack: iterate objects in offset order
authorDavid Michael Barr <b@rr-dav.id.au>
Mon, 10 Sep 2012 01:48:21 +0000 (11:48 +1000)
committerDavid Michael Barr <b@rr-dav.id.au>
Fri, 14 Sep 2012 05:52:41 +0000 (15:52 +1000)
Compute the ordering on demand and persist until the index is freed.

src/pack.c
src/pack.h

index e1fa085fd6a49afacccb33eb0d93a15e633cfa5b..9346aced61c90ee44ea6851911f6e2ef1b1a6896 100644 (file)
@@ -54,6 +54,10 @@ static int packfile_error(const char *message)
 
 static void pack_index_free(struct git_pack_file *p)
 {
+       if (p->oids) {
+               git__free(p->oids);
+               p->oids = NULL;
+       }
        if (p->index_map.data) {
                git_futils_mmap_free(&p->index_map);
                p->index_map.data = NULL;
@@ -686,13 +690,16 @@ static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_
        }
 }
 
+static int git__memcmp4(const void *a, const void *b) {
+       return memcmp(a, b, 4);
+}
+
 int git_pack_foreach_entry(
        struct git_pack_file *p,
        int (*cb)(git_oid *oid, void *data),
        void *data)
 {
        const unsigned char *index = p->index_map.data, *current;
-       unsigned stride;
        uint32_t i;
 
        if (index == NULL) {
@@ -712,21 +719,38 @@ int git_pack_foreach_entry(
 
        index += 4 * 256;
 
-       if (p->index_version > 1) {
-               stride = 20;
-       } else {
-               stride = 24;
-               index += 4;
-       }
+       if (p->oids == NULL) {
+               git_vector offsets, oids;
+               int error;
 
-       current = index;
-       for (i = 0; i < p->num_objects; i++) {
-               if (cb((git_oid *)current, data))
-                       return GIT_EUSER;
+               if ((error = git_vector_init(&oids, p->num_objects, NULL)))
+                       return error;
+
+               if ((error = git_vector_init(&offsets, p->num_objects, git__memcmp4)))
+                       return error;
 
-               current += stride;
+               if (p->index_version > 1) {
+                       const unsigned char *off = index + 24 * p->num_objects;
+                       for (i = 0; i < p->num_objects; i++)
+                               git_vector_insert(&offsets, (void*)&off[4 * i]);
+                       git_vector_sort(&offsets);
+                       git_vector_foreach(&offsets, i, current)
+                               git_vector_insert(&oids, (void*)&index[5 * (current - off)]);
+               } else {
+                       for (i = 0; i < p->num_objects; i++)
+                               git_vector_insert(&offsets, (void*)&index[24 * i]);
+                       git_vector_sort(&offsets);
+                       git_vector_foreach(&offsets, i, current)
+                               git_vector_insert(&oids, (void*)&current[4]);
+               }
+               git_vector_free(&offsets);
+               p->oids = (git_oid **)oids.contents;
        }
 
+       for (i = 0; i < p->num_objects; i++)
+               if (cb(p->oids[i], data))
+                       return GIT_EUSER;
+
        return 0;
 }
 
index 178545675d95905341287b6f5da2b3c2994eb72e..af87b7cd5abef04c80293bd024f3f91f4d578aaf 100644 (file)
@@ -64,6 +64,7 @@ struct git_pack_file {
        unsigned pack_local:1, pack_keep:1, has_cache:1;
        git_oid sha1;
        git_vector cache;
+       git_oid **oids;
 
        /* something like ".git/objects/pack/xxxxx.pack" */
        char pack_name[GIT_FLEX_ARRAY]; /* more */