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 <gitster@pobox.com>
This commit is contained in:
Junio C Hamano
2011-10-18 15:53:23 -07:00
parent 49b5f81713
commit 93104a2742
5 changed files with 79 additions and 0 deletions

View File

@@ -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"

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,