Skip to content

Commit f6667c5

Browse files
committed
pretty: %G[?GS] placeholders
Add new placeholders related to the GPG signature on signed commits. - %GG to show the raw verification message from GPG; - %G? to show either "G" for Good, "B" for Bad; - %GS to show the name of the signer. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 247503f commit f6667c5

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

pretty.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "notes.h"
1010
#include "color.h"
1111
#include "reflog-walk.h"
12+
#include "gpg-interface.h"
1213

1314
static char *user_format;
1415
static struct cmt_fmt_map {
@@ -640,6 +641,12 @@ struct format_commit_context {
640641
const struct pretty_print_context *pretty_ctx;
641642
unsigned commit_header_parsed:1;
642643
unsigned commit_message_parsed:1;
644+
unsigned commit_signature_parsed:1;
645+
struct {
646+
char *gpg_output;
647+
char good_bad;
648+
char *signer;
649+
} signature;
643650
char *message;
644651
size_t width, indent1, indent2;
645652

@@ -822,6 +829,59 @@ static void rewrap_message_tail(struct strbuf *sb,
822829
c->indent2 = new_indent2;
823830
}
824831

832+
static struct {
833+
char result;
834+
const char *check;
835+
} signature_check[] = {
836+
{ 'G', ": Good signature from " },
837+
{ 'B', ": BAD signature from " },
838+
};
839+
840+
static void parse_signature_lines(struct format_commit_context *ctx)
841+
{
842+
const char *buf = ctx->signature.gpg_output;
843+
int i;
844+
845+
for (i = 0; i < ARRAY_SIZE(signature_check); i++) {
846+
const char *found = strstr(buf, signature_check[i].check);
847+
const char *next;
848+
if (!found)
849+
continue;
850+
ctx->signature.good_bad = signature_check[i].result;
851+
found += strlen(signature_check[i].check);
852+
next = strchrnul(found, '\n');
853+
ctx->signature.signer = xmemdupz(found, next - found);
854+
break;
855+
}
856+
}
857+
858+
static void parse_commit_signature(struct format_commit_context *ctx)
859+
{
860+
struct strbuf payload = STRBUF_INIT;
861+
struct strbuf signature = STRBUF_INIT;
862+
struct strbuf gpg_output = STRBUF_INIT;
863+
int status;
864+
865+
ctx->commit_signature_parsed = 1;
866+
867+
if (parse_signed_commit(ctx->commit->object.sha1,
868+
&payload, &signature) <= 0)
869+
goto out;
870+
status = verify_signed_buffer(payload.buf, payload.len,
871+
signature.buf, signature.len,
872+
&gpg_output);
873+
if (status && !gpg_output.len)
874+
goto out;
875+
ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);
876+
parse_signature_lines(ctx);
877+
878+
out:
879+
strbuf_release(&gpg_output);
880+
strbuf_release(&payload);
881+
strbuf_release(&signature);
882+
}
883+
884+
825885
static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
826886
void *context)
827887
{
@@ -974,6 +1034,30 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
9741034
return 0;
9751035
}
9761036

1037+
if (placeholder[0] == 'G') {
1038+
if (!c->commit_signature_parsed)
1039+
parse_commit_signature(c);
1040+
switch (placeholder[1]) {
1041+
case 'G':
1042+
if (c->signature.gpg_output)
1043+
strbuf_addstr(sb, c->signature.gpg_output);
1044+
break;
1045+
case '?':
1046+
switch (c->signature.good_bad) {
1047+
case 'G':
1048+
case 'B':
1049+
strbuf_addch(sb, c->signature.good_bad);
1050+
}
1051+
break;
1052+
case 'S':
1053+
if (c->signature.signer)
1054+
strbuf_addstr(sb, c->signature.signer);
1055+
break;
1056+
}
1057+
return 2;
1058+
}
1059+
1060+
9771061
/* For the rest we have to parse the commit header. */
9781062
if (!c->commit_header_parsed)
9791063
parse_commit_header(c);
@@ -1114,6 +1198,8 @@ void format_commit_message(const struct commit *commit,
11141198

11151199
if (context.message != commit->buffer)
11161200
free(context.message);
1201+
free(context.signature.gpg_output);
1202+
free(context.signature.signer);
11171203
}
11181204

11191205
static void pp_header(const struct pretty_print_context *pp,

0 commit comments

Comments
 (0)