Skip to content

Commit 824958e

Browse files
committed
log-tree: show mergetag in log --show-signature output
A commit object that merges a signed tag records the "mergetag" extended header. Check the validity of the GPG signature on it, and show it in a way similar to how "gpgsig" extended header is shown. Signed-off-by: Junio C Hamano <[email protected]>
1 parent c6b3ec4 commit 824958e

File tree

1 file changed

+75
-1
lines changed

1 file changed

+75
-1
lines changed

log-tree.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,78 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
443443
strbuf_release(&signature);
444444
}
445445

446+
static int which_parent(const unsigned char *sha1, const struct commit *commit)
447+
{
448+
int nth;
449+
const struct commit_list *parent;
450+
451+
for (nth = 0, parent = commit->parents; parent; parent = parent->next) {
452+
if (!hashcmp(parent->item->object.sha1, sha1))
453+
return nth;
454+
nth++;
455+
}
456+
return -1;
457+
}
458+
459+
static void show_one_mergetag(struct rev_info *opt,
460+
struct commit_extra_header *extra,
461+
struct commit *commit)
462+
{
463+
unsigned char sha1[20];
464+
struct tag *tag;
465+
struct strbuf verify_message;
466+
int status, nth;
467+
size_t payload_size, gpg_message_offset;
468+
469+
hash_sha1_file(extra->value, extra->len, typename(OBJ_TAG), sha1);
470+
tag = lookup_tag(sha1);
471+
if (!tag)
472+
return; /* error message already given */
473+
474+
strbuf_init(&verify_message, 256);
475+
if (parse_tag_buffer(tag, extra->value, extra->len))
476+
strbuf_addstr(&verify_message, "malformed mergetag\n");
477+
else if ((nth = which_parent(tag->tagged->sha1, commit)) < 0)
478+
strbuf_addf(&verify_message, "tag %s names a non-parent %s\n",
479+
tag->tag, tag->tagged->sha1);
480+
else
481+
strbuf_addf(&verify_message,
482+
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
483+
gpg_message_offset = verify_message.len;
484+
485+
payload_size = parse_signature(extra->value, extra->len);
486+
if ((extra->len <= payload_size) ||
487+
(verify_signed_buffer(extra->value, payload_size,
488+
extra->value + payload_size,
489+
extra->len - payload_size,
490+
&verify_message) &&
491+
verify_message.len <= gpg_message_offset)) {
492+
strbuf_addstr(&verify_message, "No signature\n");
493+
status = -1;
494+
}
495+
else if (strstr(verify_message.buf + gpg_message_offset,
496+
": Good signature from "))
497+
status = 0;
498+
else
499+
status = -1;
500+
501+
show_sig_lines(opt, status, verify_message.buf);
502+
strbuf_release(&verify_message);
503+
}
504+
505+
static void show_mergetag(struct rev_info *opt, struct commit *commit)
506+
{
507+
struct commit_extra_header *extra, *to_free;
508+
509+
to_free = read_commit_extra_headers(commit, NULL);
510+
for (extra = to_free; extra; extra = extra->next) {
511+
if (strcmp(extra->key, "mergetag"))
512+
continue; /* not a merge tag */
513+
show_one_mergetag(opt, extra, commit);
514+
}
515+
free_commit_extra_headers(to_free);
516+
}
517+
446518
void show_log(struct rev_info *opt)
447519
{
448520
struct strbuf msgbuf = STRBUF_INIT;
@@ -554,8 +626,10 @@ void show_log(struct rev_info *opt)
554626
}
555627
}
556628

557-
if (opt->show_signature)
629+
if (opt->show_signature) {
558630
show_signature(opt, commit);
631+
show_mergetag(opt, commit);
632+
}
559633

560634
if (!commit->buffer)
561635
return;

0 commit comments

Comments
 (0)