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 <gitster@pobox.com>
Junio C Hamano committed
Jan 4, 2012 at 13:51 UTC
824958e50b250e957998626a21763603ca30e832
1 file changed
+75
-1
log-tree.c
+75
-1
@@ -443,6 +443,78 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
443
strbuf_release(&signature);
444
}
445
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
+
518
void show_log(struct rev_info *opt)
519
{
520
struct strbuf msgbuf = STRBUF_INIT;
@@ -554,8 +626,10 @@ void show_log(struct rev_info *opt)
626
}
627
}
628
557
- if (opt->show_signature)
629
+ if (opt->show_signature) {
630
show_signature(opt, commit);
631
+ show_mergetag(opt, commit);
632
+ }
633
634
if (!commit->buffer)
635
return;