Merge branch 'jc/tartree' into jc/builtin-n-tar-tree
[gitweb.git] / index-pack.c
index badbeab70e2d8426a4e11c4ecda3b0f4ed518206..b39953dc698aae25f79caa9553e13bca6cd4e986 100644 (file)
@@ -2,6 +2,10 @@
 #include "delta.h"
 #include "pack.h"
 #include "csum-file.h"
+#include "blob.h"
+#include "commit.h"
+#include "tag.h"
+#include "tree.h"
 
 static const char index_pack_usage[] =
 "git-index-pack [-o index-file] pack-file";
@@ -68,9 +72,9 @@ static void parse_pack_header(void)
        hdr = (void *)pack_base;
        if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
                die("packfile '%s' signature mismatch", pack_name);
-       if (hdr->hdr_version != htonl(PACK_VERSION))
-               die("packfile '%s' version %d different from ours %d",
-                   pack_name, ntohl(hdr->hdr_version), PACK_VERSION);
+       if (!pack_version_ok(hdr->hdr_version))
+               die("packfile '%s' version %d unsupported",
+                   pack_name, ntohl(hdr->hdr_version));
 
        nr_objects = ntohl(hdr->hdr_entries);
 
@@ -224,10 +228,10 @@ static void sha1_object(const void *data, unsigned long size,
        const char *type_str;
 
        switch (type) {
-       case OBJ_COMMIT: type_str = "commit"; break;
-       case OBJ_TREE:   type_str = "tree"; break;
-       case OBJ_BLOB:   type_str = "blob"; break;
-       case OBJ_TAG:    type_str = "tag"; break;
+       case OBJ_COMMIT: type_str = commit_type; break;
+       case OBJ_TREE:   type_str = tree_type; break;
+       case OBJ_BLOB:   type_str = blob_type; break;
+       case OBJ_TAG:    type_str = tag_type; break;
        default:
                die("bad type %d", type);
        }
@@ -349,20 +353,27 @@ static int sha1_compare(const void *_a, const void *_b)
        return memcmp(a->sha1, b->sha1, 20);
 }
 
-static void write_index_file(const char *index_name)
+static void write_index_file(const char *index_name, unsigned char *sha1)
 {
        struct sha1file *f;
-       struct object_entry **sorted_by_sha =
-               xcalloc(nr_objects, sizeof(struct object_entry *));
-       struct object_entry **list = sorted_by_sha;
-       struct object_entry **last = sorted_by_sha + nr_objects;
+       struct object_entry **sorted_by_sha, **list, **last;
        unsigned int array[256];
        int i;
+       SHA_CTX ctx;
+
+       if (nr_objects) {
+               sorted_by_sha =
+                       xcalloc(nr_objects, sizeof(struct object_entry *));
+               list = sorted_by_sha;
+               last = sorted_by_sha + nr_objects;
+               for (i = 0; i < nr_objects; ++i)
+                       sorted_by_sha[i] = &objects[i];
+               qsort(sorted_by_sha, nr_objects, sizeof(sorted_by_sha[0]),
+                     sha1_compare);
 
-       for (i = 0; i < nr_objects; ++i)
-               sorted_by_sha[i] = &objects[i];
-       qsort(sorted_by_sha, nr_objects, sizeof(sorted_by_sha[0]),
-             sha1_compare);
+       }
+       else
+               sorted_by_sha = list = last = NULL;
 
        unlink(index_name);
        f = sha1create("%s", index_name);
@@ -385,6 +396,11 @@ static void write_index_file(const char *index_name)
        }
        sha1write(f, array, 256 * sizeof(int));
 
+       /* recompute the SHA1 hash of sorted object names.
+        * currently pack-objects does not do this, but that
+        * can be fixed.
+        */
+       SHA1_Init(&ctx);
        /*
         * Write the actual SHA1 entries..
         */
@@ -394,10 +410,12 @@ static void write_index_file(const char *index_name)
                unsigned int offset = htonl(obj->offset);
                sha1write(f, &offset, 4);
                sha1write(f, obj->sha1, 20);
+               SHA1_Update(&ctx, obj->sha1, 20);
        }
        sha1write(f, pack_base + pack_size - 20, 20);
        sha1close(f, NULL, 1);
        free(sorted_by_sha);
+       SHA1_Final(sha1, &ctx);
 }
 
 int main(int argc, char **argv)
@@ -405,6 +423,7 @@ int main(int argc, char **argv)
        int i;
        char *index_name = NULL;
        char *index_name_buf = NULL;
+       unsigned char sha1[20];
 
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
@@ -431,7 +450,7 @@ int main(int argc, char **argv)
                if (len < 5 || strcmp(pack_name + len - 5, ".pack"))
                        die("packfile name '%s' does not end with '.pack'",
                            pack_name);
-               index_name_buf = xmalloc(len - 1);
+               index_name_buf = xmalloc(len);
                memcpy(index_name_buf, pack_name, len - 5);
                strcpy(index_name_buf + len - 5, ".idx");
                index_name = index_name_buf;
@@ -443,9 +462,11 @@ int main(int argc, char **argv)
        deltas = xcalloc(nr_objects, sizeof(struct delta_entry));
        parse_pack_objects();
        free(deltas);
-       write_index_file(index_name);
+       write_index_file(index_name, sha1);
        free(objects);
        free(index_name_buf);
 
+       printf("%s\n", sha1_to_hex(sha1));
+
        return 0;
 }