From 93104a2742d01adf97f173bda63c12382c77aae2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 18 Oct 2011 15:53:23 -0700 Subject: [PATCH] log: --show-signature This teaches the "log" family of commands to pass the GPG signature in the commit objects to "gpg --verify" via the verify_signed_buffer() interface used to verify signed tag objects. E.g. $ git show --show-signature -s HEAD shows GPG output in the header part of the output. Signed-off-by: Junio C Hamano --- commit.c | 34 ++++++++++++++++++++++++++++++++++ commit.h | 3 +++ log-tree.c | 39 +++++++++++++++++++++++++++++++++++++++ revision.c | 2 ++ revision.h | 1 + 5 files changed, 79 insertions(+) diff --git a/commit.c b/commit.c index 4bff3cdaae..93045a2cda 100644 --- a/commit.c +++ b/commit.c @@ -848,6 +848,40 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid) 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_header, saw_signature = -1; + char *line; + + if (!buffer || type != OBJ_COMMIT) + goto cleanup; + + line = buffer; + in_header = 1; + saw_signature = 0; + while (*line) { + char *next = strchrnul(line, '\n'); + if (*next) + next++; + if (in_header && !prefixcmp(line, gpg_sig_header)) { + const char *sig = line + gpg_sig_header_len; + strbuf_add(signature, sig, next - sig); + saw_signature = 1; + } else { + strbuf_add(payload, line, next - line); + } + if (*line == '\n') + in_header = 0; + line = next; + } + cleanup: + free(buffer); + return saw_signature; +} static const char commit_utf8_warn[] = "Warning: commit message does not conform to UTF-8.\n" diff --git a/commit.h b/commit.h index 8c2419b51f..1885471b8b 100644 --- a/commit.h +++ b/commit.h @@ -177,4 +177,7 @@ extern int commit_tree(const char *msg, unsigned char *tree, struct commit_list *parents, unsigned char *ret, const char *author, const char *sign_commit); +extern int parse_signed_commit(const unsigned char *sha1, + struct strbuf *message, struct strbuf *signature); + #endif /* COMMIT_H */ diff --git a/log-tree.c b/log-tree.c index 24c295ea1d..f7b6976d9f 100644 --- a/log-tree.c +++ b/log-tree.c @@ -8,6 +8,7 @@ #include "refs.h" #include "string-list.h" #include "color.h" +#include "gpg-interface.h" struct decoration name_decoration = { "object names" }; @@ -395,6 +396,41 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, *extra_headers_p = extra_headers; } +static void show_signature(struct rev_info *opt, struct commit *commit) +{ + struct strbuf payload = STRBUF_INIT; + struct strbuf signature = STRBUF_INIT; + struct strbuf gpg_output = STRBUF_INIT; + int status; + const char *color, *reset, *bol, *eol; + + if (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0) + goto out; + + status = verify_signed_buffer(payload.buf, payload.len, + signature.buf, signature.len, + &gpg_output); + if (status && !gpg_output.len) + strbuf_addstr(&gpg_output, "No signature\n"); + + color = diff_get_color_opt(&opt->diffopt, + status ? DIFF_WHITESPACE : DIFF_FRAGINFO); + reset = diff_get_color_opt(&opt->diffopt, DIFF_RESET); + + bol = gpg_output.buf; + while (*bol) { + eol = strchrnul(bol, '\n'); + printf("%s%.*s%s%s", color, (int)(eol - bol), bol, reset, + *eol ? "\n" : ""); + bol = (*eol) ? (eol + 1) : eol; + } + + out: + strbuf_release(&gpg_output); + strbuf_release(&payload); + strbuf_release(&signature); +} + void show_log(struct rev_info *opt) { struct strbuf msgbuf = STRBUF_INIT; @@ -502,6 +538,9 @@ void show_log(struct rev_info *opt) } } + if (opt->show_signature) + show_signature(opt, commit); + if (!commit->buffer) return; diff --git a/revision.c b/revision.c index c46cfaa3e4..860a3128a3 100644 --- a/revision.c +++ b/revision.c @@ -1381,6 +1381,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->show_notes = 1; revs->show_notes_given = 1; revs->notes_opt.use_default_notes = 1; + } else if (!strcmp(arg, "--show-signature")) { + revs->show_signature = 1; } else if (!prefixcmp(arg, "--show-notes=") || !prefixcmp(arg, "--notes=")) { struct strbuf buf = STRBUF_INIT; diff --git a/revision.h b/revision.h index 3d64adad18..198bb95894 100644 --- a/revision.h +++ b/revision.h @@ -89,6 +89,7 @@ struct rev_info { show_merge:1, show_notes:1, show_notes_given:1, + show_signature:1, pretty_given:1, abbrev_commit:1, abbrev_commit_given:1, -- 2.11.4.GIT