diff options
-rw-r--r-- | commit.c | 44 | ||||
-rw-r--r-- | commit.h | 2 | ||||
-rw-r--r-- | log-tree.c | 2 |
3 files changed, 38 insertions, 10 deletions
@@ -1083,14 +1083,42 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid) return 0; } -int parse_signed_commit(const unsigned char *sha1, +/* + * Return the contents of the object pointed to by commit, as + * if read by read_sha1_file. However, in cases where the commit's + * data is already in memory, return that as an optimization. + * + * The resulting buffer may or may not be freshly allocated, + * and should only be freed by free_commit_buffer. + */ +static const char *read_commit_buffer(const struct commit *commit, + enum object_type *type, + unsigned long *size) +{ + if (commit->buffer) { + *type = OBJ_COMMIT; + *size = strlen(commit->buffer); + return commit->buffer; + } + + return read_sha1_file(commit->object.sha1, type, size); +} + +static void free_commit_buffer(const char *buffer, const struct commit *commit) +{ + if (buffer != commit->buffer) + free((char *)buffer); +} + +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 = read_commit_buffer(commit, &type, &size); int in_signature, saw_signature = -1; - char *line, *tail; + const char *line, *tail; if (!buffer || type != OBJ_COMMIT) goto cleanup; @@ -1101,7 +1129,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] == ' ') @@ -1123,7 +1151,7 @@ int parse_signed_commit(const unsigned char *sha1, line = next; } cleanup: - free(buffer); + free_commit_buffer(buffer, commit); return saw_signature; } @@ -1216,7 +1244,7 @@ void check_commit_signature(const struct commit* commit, struct signature_check sigc->result = 'N'; - if (parse_signed_commit(commit->object.sha1, + if (parse_signed_commit(commit, &payload, &signature) <= 0) goto out; status = verify_signed_buffer(payload.buf, payload.len, @@ -1263,10 +1291,10 @@ 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); + const char *buffer = read_commit_buffer(commit, &type, &size); if (buffer && type == OBJ_COMMIT) extra = read_commit_extra_header_lines(buffer, size, exclude); - free(buffer); + free_commit_buffer(buffer, commit); return extra; } @@ -257,7 +257,7 @@ struct merge_remote_desc { */ struct commit *get_merge_parent(const char *name); -extern int parse_signed_commit(const unsigned char *sha1, +extern int parse_signed_commit(const struct commit *commit, struct strbuf *message, struct strbuf *signature); extern void print_commit_list(struct commit_list *list, const char *format_cur, diff --git a/log-tree.c b/log-tree.c index 1982631ca4..2affe8150d 100644 --- a/log-tree.c +++ b/log-tree.c @@ -376,7 +376,7 @@ static void show_signature(struct rev_info *opt, struct commit *commit) struct strbuf gpg_output = STRBUF_INIT; int status; - 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, |