diff options
author | Junio C Hamano <gitster@pobox.com> | 2012-01-05 11:00:38 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2012-01-05 11:00:49 -0800 |
commit | 9d3d78435f2735b74afc74e9c5a735c27c026d33 (patch) | |
tree | 8f66df5b090f6163698d66cc9dd7a522ae359dfd /commit.c | |
parent | 0074d18dc0d816f9842d3e0e1cd0b26341715b37 (diff) | |
parent | 0c5e70f041bfda8b3899d13694a9093b41fafa19 (diff) | |
download | git-9d3d78435f2735b74afc74e9c5a735c27c026d33.tar.gz |
Merge branch 'jc/signed-commit' and 'jc/pull-signed-tag'
They both use the extended headers in commit objects, and the former has
necessary infrastructure to show them that is useful to view the result of
the latter.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'commit.c')
-rw-r--r-- | commit.c | 92 |
1 files changed, 89 insertions, 3 deletions
@@ -6,6 +6,7 @@ #include "diff.h" #include "revision.h" #include "notes.h" +#include "gpg-interface.h" int save_commit_buffer = 1; @@ -840,6 +841,86 @@ struct commit_list *reduce_heads(struct commit_list *heads) return result; } +static const char gpg_sig_header[] = "gpgsig"; +static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1; + +static int do_sign_commit(struct strbuf *buf, const char *keyid) +{ + struct strbuf sig = STRBUF_INIT; + int inspos, copypos; + + /* find the end of the header */ + inspos = strstr(buf->buf, "\n\n") - buf->buf + 1; + + if (!keyid || !*keyid) + keyid = get_signing_key(); + if (sign_buffer(buf, &sig, keyid)) { + strbuf_release(&sig); + return -1; + } + + for (copypos = 0; sig.buf[copypos]; ) { + const char *bol = sig.buf + copypos; + const char *eol = strchrnul(bol, '\n'); + int len = (eol - bol) + !!*eol; + + if (!copypos) { + strbuf_insert(buf, inspos, gpg_sig_header, gpg_sig_header_len); + inspos += gpg_sig_header_len; + } + strbuf_insert(buf, inspos++, " ", 1); + strbuf_insert(buf, inspos, bol, len); + inspos += len; + copypos += len; + } + strbuf_release(&sig); + return 0; +} + +int parse_signed_commit(const unsigned char *sha1, + struct strbuf *payload, struct strbuf *signature) +{ + unsigned long size; + enum object_type type; + char *buffer = read_sha1_file(sha1, &type, &size); + int in_signature, saw_signature = -1; + char *line, *tail; + + if (!buffer || type != OBJ_COMMIT) + goto cleanup; + + line = buffer; + tail = buffer + size; + in_signature = 0; + saw_signature = 0; + while (line < tail) { + const char *sig = NULL; + char *next = memchr(line, '\n', tail - line); + + next = next ? next + 1 : tail; + if (in_signature && line[0] == ' ') + sig = line + 1; + else if (!prefixcmp(line, gpg_sig_header) && + line[gpg_sig_header_len] == ' ') + sig = line + gpg_sig_header_len + 1; + if (sig) { + strbuf_add(signature, sig, next - sig); + saw_signature = 1; + in_signature = 1; + } else { + if (*line == '\n') + /* dump the whole remainder of the buffer */ + next = tail; + strbuf_add(payload, line, next - line); + in_signature = 0; + } + line = next; + } + cleanup: + free(buffer); + return saw_signature; +} + static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail) { struct merge_remote_desc *desc; @@ -975,13 +1056,14 @@ void free_commit_extra_headers(struct commit_extra_header *extra) int commit_tree(const char *msg, unsigned char *tree, struct commit_list *parents, unsigned char *ret, - const char *author) + const char *author, const char *sign_commit) { struct commit_extra_header *extra = NULL, **tail = &extra; int result; append_merge_tag_headers(parents, &tail); - result = commit_tree_extended(msg, tree, parents, ret, author, extra); + result = commit_tree_extended(msg, tree, parents, ret, + author, sign_commit, extra); free_commit_extra_headers(extra); return result; } @@ -993,7 +1075,8 @@ static const char commit_utf8_warn[] = int commit_tree_extended(const char *msg, unsigned char *tree, struct commit_list *parents, unsigned char *ret, - const char *author, struct commit_extra_header *extra) + const char *author, const char *sign_commit, + struct commit_extra_header *extra) { int result; int encoding_is_utf8; @@ -1043,6 +1126,9 @@ int commit_tree_extended(const char *msg, unsigned char *tree, if (encoding_is_utf8 && !is_utf8(buffer.buf)) fprintf(stderr, commit_utf8_warn); + if (sign_commit && do_sign_commit(&buffer, sign_commit)) + return -1; + result = write_sha1_file(buffer.buf, buffer.len, commit_type, ret); strbuf_release(&buffer); return result; |