difftool: don't assume that default sh is sane
[gitweb.git] / commit.c
index 1903dde2850ea2a55a88895f5d69553fcb06f459..65179f96eecc85082f9bf3f0312676878d92861d 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -18,19 +18,6 @@ int save_commit_buffer = 1;
 
 const char *commit_type = "commit";
 
-static struct commit *check_commit(struct object *obj,
-                                  const unsigned char *sha1,
-                                  int quiet)
-{
-       if (obj->type != OBJ_COMMIT) {
-               if (!quiet)
-                       error("Object %s is a %s, not a commit",
-                             sha1_to_hex(sha1), typename(obj->type));
-               return NULL;
-       }
-       return (struct commit *) obj;
-}
-
 struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
                                              int quiet)
 {
@@ -38,7 +25,7 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
 
        if (!obj)
                return NULL;
-       return check_commit(obj, sha1, quiet);
+       return object_as_type(obj, OBJ_COMMIT, quiet);
 }
 
 struct commit *lookup_commit_reference(const unsigned char *sha1)
@@ -61,13 +48,9 @@ struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_n
 struct commit *lookup_commit(const unsigned char *sha1)
 {
        struct object *obj = lookup_object(sha1);
-       if (!obj) {
-               struct commit *c = alloc_commit_node();
-               return create_object(sha1, OBJ_COMMIT, c);
-       }
-       if (!obj->type)
-               obj->type = OBJ_COMMIT;
-       return check_commit(obj, sha1, 0);
+       if (!obj)
+               return create_object(sha1, alloc_commit_node());
+       return object_as_type(obj, OBJ_COMMIT, 0);
 }
 
 struct commit *lookup_commit_reference_by_name(const char *name)
@@ -245,19 +228,31 @@ int unregister_shallow(const unsigned char *sha1)
        return 0;
 }
 
-void set_commit_buffer(struct commit *commit, void *buffer)
+struct commit_buffer {
+       void *buffer;
+       unsigned long size;
+};
+define_commit_slab(buffer_slab, struct commit_buffer);
+static struct buffer_slab buffer_slab = COMMIT_SLAB_INIT(1, buffer_slab);
+
+void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
 {
-       commit->buffer = buffer;
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       v->buffer = buffer;
+       v->size = size;
 }
 
-const void *get_cached_commit_buffer(const struct commit *commit)
+const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
 {
-       return commit->buffer;
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       if (sizep)
+               *sizep = v->size;
+       return v->buffer;
 }
 
-const void *get_commit_buffer(const struct commit *commit)
+const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
 {
-       const void *ret = get_cached_commit_buffer(commit);
+       const void *ret = get_cached_commit_buffer(commit, sizep);
        if (!ret) {
                enum object_type type;
                unsigned long size;
@@ -268,26 +263,38 @@ const void *get_commit_buffer(const struct commit *commit)
                if (type != OBJ_COMMIT)
                        die("expected commit for %s, got %s",
                            sha1_to_hex(commit->object.sha1), typename(type));
+               if (sizep)
+                       *sizep = size;
        }
        return ret;
 }
 
 void unuse_commit_buffer(const struct commit *commit, const void *buffer)
 {
-       if (commit->buffer != buffer)
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       if (v->buffer != buffer)
                free((void *)buffer);
 }
 
 void free_commit_buffer(struct commit *commit)
 {
-       free(commit->buffer);
-       commit->buffer = NULL;
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       free(v->buffer);
+       v->buffer = NULL;
+       v->size = 0;
 }
 
-const void *detach_commit_buffer(struct commit *commit)
+const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
 {
-       void *ret = commit->buffer;
-       commit->buffer = NULL;
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       void *ret;
+
+       ret = v->buffer;
+       if (sizep)
+               *sizep = v->size;
+
+       v->buffer = NULL;
+       v->size = 0;
        return ret;
 }
 
@@ -368,7 +375,7 @@ int parse_commit(struct commit *item)
        }
        ret = parse_commit_buffer(item, buffer, size);
        if (save_commit_buffer && !ret) {
-               set_commit_buffer(item, buffer);
+               set_commit_buffer(item, buffer, size);
                return 0;
        }
        free(buffer);
@@ -583,7 +590,7 @@ static void record_author_date(struct author_date_slab *author_date,
                               struct commit *commit)
 {
        const char *buf, *line_end, *ident_line;
-       const char *buffer = get_commit_buffer(commit);
+       const char *buffer = get_commit_buffer(commit, NULL);
        struct ident_split ident;
        char *date_end;
        unsigned long date;
@@ -1065,7 +1072,7 @@ struct commit_list *reduce_heads(struct commit_list *heads)
                p->item->object.flags |= STALE;
                num_head++;
        }
-       array = xcalloc(sizeof(*array), num_head);
+       array = xcalloc(num_head, sizeof(*array));
        for (p = heads, i = 0; p; p = p->next) {
                if (p->item->object.flags & STALE) {
                        array[i++] = p->item;
@@ -1114,17 +1121,14 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
        return 0;
 }
 
-int parse_signed_commit(const unsigned char *sha1,
+int parse_signed_commit(const struct commit *commit,
                        struct strbuf *payload, struct strbuf *signature)
 {
+
        unsigned long size;
-       enum object_type type;
-       char *buffer = read_sha1_file(sha1, &type, &size);
+       const char *buffer = get_commit_buffer(commit, &size);
        int in_signature, saw_signature = -1;
-       char *line, *tail;
-
-       if (!buffer || type != OBJ_COMMIT)
-               goto cleanup;
+       const char *line, *tail;
 
        line = buffer;
        tail = buffer + size;
@@ -1132,7 +1136,7 @@ int parse_signed_commit(const unsigned char *sha1,
        saw_signature = 0;
        while (line < tail) {
                const char *sig = NULL;
-               char *next = memchr(line, '\n', tail - line);
+               const char *next = memchr(line, '\n', tail - line);
 
                next = next ? next + 1 : tail;
                if (in_signature && line[0] == ' ')
@@ -1153,8 +1157,7 @@ int parse_signed_commit(const unsigned char *sha1,
                }
                line = next;
        }
- cleanup:
-       free(buffer);
+       unuse_commit_buffer(commit, buffer);
        return saw_signature;
 }
 
@@ -1245,8 +1248,7 @@ void check_commit_signature(const struct commit* commit, struct signature_check
 
        sigc->result = 'N';
 
-       if (parse_signed_commit(commit->object.sha1,
-                               &payload, &signature) <= 0)
+       if (parse_signed_commit(commit, &payload, &signature) <= 0)
                goto out;
        status = verify_signed_buffer(payload.buf, payload.len,
                                      signature.buf, signature.len,
@@ -1291,11 +1293,9 @@ struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
 {
        struct commit_extra_header *extra = NULL;
        unsigned long size;
-       enum object_type type;
-       char *buffer = read_sha1_file(commit->object.sha1, &type, &size);
-       if (buffer && type == OBJ_COMMIT)
-               extra = read_commit_extra_header_lines(buffer, size, exclude);
-       free(buffer);
+       const char *buffer = get_commit_buffer(commit, &size);
+       extra = read_commit_extra_header_lines(buffer, size, exclude);
+       unuse_commit_buffer(commit, buffer);
        return extra;
 }