Skip to content

Commit

Permalink
log: --show-signature
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Junio C Hamano committed Nov 13, 2011
1 parent ba3c69a commit 0c37f1f
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 0 deletions.
44 changes: 44 additions & 0 deletions commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,50 @@ 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_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;
Expand Down
2 changes: 2 additions & 0 deletions commit.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,6 @@ struct merge_remote_desc {
*/
struct commit *get_merge_parent(const char *name);

extern int parse_signed_commit(const unsigned char *sha1,
struct strbuf *message, struct strbuf *signature);
#endif /* COMMIT_H */
39 changes: 39 additions & 0 deletions log-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "refs.h"
#include "string-list.h"
#include "color.h"
#include "gpg-interface.h"

struct decoration name_decoration = { "object names" };

Expand Down Expand Up @@ -403,6 +404,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;
Expand Down Expand Up @@ -514,6 +550,9 @@ void show_log(struct rev_info *opt)
}
}

if (opt->show_signature)
show_signature(opt, commit);

if (!commit->buffer)
return;

Expand Down
2 changes: 2 additions & 0 deletions revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,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;
Expand Down
1 change: 1 addition & 0 deletions revision.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,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,
Expand Down

0 comments on commit 0c37f1f

Please sign in to comment.