Skip to content

Commit 0c37f1f

Browse files
committed
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 <[email protected]>
1 parent ba3c69a commit 0c37f1f

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

commit.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,50 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
877877
return 0;
878878
}
879879

880+
int parse_signed_commit(const unsigned char *sha1,
881+
struct strbuf *payload, struct strbuf *signature)
882+
{
883+
unsigned long size;
884+
enum object_type type;
885+
char *buffer = read_sha1_file(sha1, &type, &size);
886+
int in_signature, saw_signature = -1;
887+
char *line, *tail;
888+
889+
if (!buffer || type != OBJ_COMMIT)
890+
goto cleanup;
891+
892+
line = buffer;
893+
tail = buffer + size;
894+
in_signature = 0;
895+
saw_signature = 0;
896+
while (line < tail) {
897+
const char *sig = NULL;
898+
char *next = memchr(line, '\n', tail - line);
899+
900+
next = next ? next + 1 : tail;
901+
if (in_signature && line[0] == ' ')
902+
sig = line + 1;
903+
else if (!prefixcmp(line, gpg_sig_header) &&
904+
line[gpg_sig_header_len] == ' ')
905+
sig = line + gpg_sig_header_len + 1;
906+
if (sig) {
907+
strbuf_add(signature, sig, next - sig);
908+
saw_signature = 1;
909+
in_signature = 1;
910+
} else {
911+
if (*line == '\n')
912+
/* dump the whole remainder of the buffer */
913+
next = tail;
914+
strbuf_add(payload, line, next - line);
915+
in_signature = 0;
916+
}
917+
line = next;
918+
}
919+
cleanup:
920+
free(buffer);
921+
return saw_signature;
922+
}
923+
880924
static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail)
881925
{
882926
struct merge_remote_desc *desc;

commit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,6 @@ struct merge_remote_desc {
218218
*/
219219
struct commit *get_merge_parent(const char *name);
220220

221+
extern int parse_signed_commit(const unsigned char *sha1,
222+
struct strbuf *message, struct strbuf *signature);
221223
#endif /* COMMIT_H */

log-tree.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "refs.h"
99
#include "string-list.h"
1010
#include "color.h"
11+
#include "gpg-interface.h"
1112

1213
struct decoration name_decoration = { "object names" };
1314

@@ -403,6 +404,41 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
403404
*extra_headers_p = extra_headers;
404405
}
405406

407+
static void show_signature(struct rev_info *opt, struct commit *commit)
408+
{
409+
struct strbuf payload = STRBUF_INIT;
410+
struct strbuf signature = STRBUF_INIT;
411+
struct strbuf gpg_output = STRBUF_INIT;
412+
int status;
413+
const char *color, *reset, *bol, *eol;
414+
415+
if (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0)
416+
goto out;
417+
418+
status = verify_signed_buffer(payload.buf, payload.len,
419+
signature.buf, signature.len,
420+
&gpg_output);
421+
if (status && !gpg_output.len)
422+
strbuf_addstr(&gpg_output, "No signature\n");
423+
424+
color = diff_get_color_opt(&opt->diffopt,
425+
status ? DIFF_WHITESPACE : DIFF_FRAGINFO);
426+
reset = diff_get_color_opt(&opt->diffopt, DIFF_RESET);
427+
428+
bol = gpg_output.buf;
429+
while (*bol) {
430+
eol = strchrnul(bol, '\n');
431+
printf("%s%.*s%s%s", color, (int)(eol - bol), bol, reset,
432+
*eol ? "\n" : "");
433+
bol = (*eol) ? (eol + 1) : eol;
434+
}
435+
436+
out:
437+
strbuf_release(&gpg_output);
438+
strbuf_release(&payload);
439+
strbuf_release(&signature);
440+
}
441+
406442
void show_log(struct rev_info *opt)
407443
{
408444
struct strbuf msgbuf = STRBUF_INIT;
@@ -514,6 +550,9 @@ void show_log(struct rev_info *opt)
514550
}
515551
}
516552

553+
if (opt->show_signature)
554+
show_signature(opt, commit);
555+
517556
if (!commit->buffer)
518557
return;
519558

revision.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
14691469
revs->show_notes = 1;
14701470
revs->show_notes_given = 1;
14711471
revs->notes_opt.use_default_notes = 1;
1472+
} else if (!strcmp(arg, "--show-signature")) {
1473+
revs->show_signature = 1;
14721474
} else if (!prefixcmp(arg, "--show-notes=") ||
14731475
!prefixcmp(arg, "--notes=")) {
14741476
struct strbuf buf = STRBUF_INIT;

revision.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct rev_info {
110110
show_merge:1,
111111
show_notes:1,
112112
show_notes_given:1,
113+
show_signature:1,
113114
pretty_given:1,
114115
abbrev_commit:1,
115116
abbrev_commit_given:1,

0 commit comments

Comments
 (0)