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>
Junio C Hamano committed
Oct 18, 2011 at 15:53 UTC
0c37f1fce6cb7997dbb2703d35eef0dfd86c5070
5 files changed
+88
commit.c
+44
@@ -877,6 +877,50 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
877
return 0;
878
}
879
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
+
924
static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail)
925
{
926
struct merge_remote_desc *desc;
commit.h
+2
@@ -218,4 +218,6 @@ struct merge_remote_desc {
218
*/
219
struct commit *get_merge_parent(const char *name);
220
221
+extern int parse_signed_commit(const unsigned char *sha1,
222
+ struct strbuf *message, struct strbuf *signature);
223
#endif /* COMMIT_H */
log-tree.c
+39
@@ -8,6 +8,7 @@
8
#include "refs.h"
9
#include "string-list.h"
10
#include "color.h"
11
+#include "gpg-interface.h"
12
13
struct decoration name_decoration = { "object names" };
14
@@ -403,6 +404,41 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
404
*extra_headers_p = extra_headers;
405
}
406
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
+
442
void show_log(struct rev_info *opt)
443
{
444
struct strbuf msgbuf = STRBUF_INIT;
@@ -514,6 +550,9 @@ void show_log(struct rev_info *opt)
550
}
551
}
552
553
+ if (opt->show_signature)
554
+ show_signature(opt, commit);
555
+
556
if (!commit->buffer)
557
return;
558
revision.c
+2
@@ -1469,6 +1469,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
1469
revs->show_notes = 1;
1470
revs->show_notes_given = 1;
1471
revs->notes_opt.use_default_notes = 1;
1472
+ } else if (!strcmp(arg, "--show-signature")) {
1473
+ revs->show_signature = 1;
1474
} else if (!prefixcmp(arg, "--show-notes=") ||
1475
!prefixcmp(arg, "--notes=")) {
1476
struct strbuf buf = STRBUF_INIT;
revision.h
+1
@@ -110,6 +110,7 @@ struct rev_info {
110
show_merge:1,
111
show_notes:1,
112
show_notes_given:1,
113
+ show_signature:1,
114
pretty_given:1,
115
abbrev_commit:1,
116
abbrev_commit_given:1,