From: Junio C Hamano Date: Fri, 5 Apr 2013 21:15:16 +0000 (-0700) Subject: Merge branch 'sg/gpg-sig' X-Git-Tag: v1.8.3-rc0~111 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/d5fec92a7af5c42217f3d1c707191791230bdefc?ds=inline;hp=-c Merge branch 'sg/gpg-sig' Teach "merge/pull" to optionally verify and reject commits that are not signed properly. * sg/gpg-sig: pretty printing: extend %G? to include 'N' and 'U' merge/pull Check for untrusted good GPG signatures merge/pull: verify GPG signatures of commits being merged commit.c/GPG signature verification: Also look at the first GPG status line Move commit GPG signature verification to commit.c --- d5fec92a7af5c42217f3d1c707191791230bdefc diff --combined Documentation/merge-options.txt index 34a8445828,a0f022b41d..2adccf8fec --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@@ -30,8 -30,7 +30,8 @@@ set to `no` at the beginning of them --no-ff:: Create a merge commit even when the merge resolves as a - fast-forward. + fast-forward. This is the default behaviour when merging an + annotated (and possibly signed) tag. --ff-only:: Refuse to merge and exit with a non-zero status unless the @@@ -84,6 -83,11 +84,11 @@@ option can be used to override --squash Pass merge strategy specific option through to the merge strategy. + --verify-signatures:: + --no-verify-signatures:: + Verify that the commits being merged have good and trusted GPG signatures + and abort the merge in case they do not. + --summary:: --no-summary:: Synonyms to --stat and --no-stat; these are deprecated and will be diff --combined builtin/merge.c index 0d94d89e74,bac11d1605..3e2daa37c3 --- a/builtin/merge.c +++ b/builtin/merge.c @@@ -49,7 -49,7 +49,7 @@@ static const char * const builtin_merge static int show_diffstat = 1, shortlog_len = -1, squash; static int option_commit = 1, allow_fast_forward = 1; static int fast_forward_only, option_edit = -1; - static int allow_trivial = 1, have_message; + static int allow_trivial = 1, have_message, verify_signatures; static int overwrite_ignore = 1; static struct strbuf merge_msg = STRBUF_INIT; static struct strategy **use_strategies; @@@ -199,6 -199,8 +199,8 @@@ static struct option builtin_merge_opti OPT_BOOLEAN(0, "ff-only", &fast_forward_only, N_("abort if fast-forward is not possible")), OPT_RERERE_AUTOUPDATE(&allow_rerere_auto), + OPT_BOOL(0, "verify-signatures", &verify_signatures, + N_("Verify that the named commit has a valid GPG signature")), OPT_CALLBACK('s', "strategy", &use_strategies, N_("strategy"), N_("merge strategy to use"), option_parse_strategy), OPT_CALLBACK('X', "strategy-option", &xopts, N_("option=value"), @@@ -516,19 -518,6 +518,19 @@@ static void merge_name(const char *remo strbuf_release(&line); goto cleanup; } + + if (remote_head->util) { + struct merge_remote_desc *desc; + desc = merge_remote_util(remote_head); + if (desc && desc->obj && desc->obj->type == OBJ_TAG) { + strbuf_addf(msg, "%s\t\t%s '%s'\n", + sha1_to_hex(desc->obj->sha1), + typename(desc->obj->type), + remote); + goto cleanup; + } + } + strbuf_addf(msg, "%s\t\tcommit '%s'\n", sha1_to_hex(remote_head->object.sha1), remote); cleanup: @@@ -1246,6 -1235,39 +1248,39 @@@ int cmd_merge(int argc, const char **ar usage_with_options(builtin_merge_usage, builtin_merge_options); + if (verify_signatures) { + for (p = remoteheads; p; p = p->next) { + struct commit *commit = p->item; + char hex[41]; + struct signature_check signature_check; + memset(&signature_check, 0, sizeof(signature_check)); + + check_commit_signature(commit, &signature_check); + + strcpy(hex, find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV)); + switch (signature_check.result) { + case 'G': + break; + case 'U': + die(_("Commit %s has an untrusted GPG signature, " + "allegedly by %s."), hex, signature_check.signer); + case 'B': + die(_("Commit %s has a bad GPG signature " + "allegedly by %s."), hex, signature_check.signer); + default: /* 'N' */ + die(_("Commit %s does not have a GPG signature."), hex); + } + if (verbosity >= 0 && signature_check.result == 'G') + printf(_("Commit %s has a good GPG signature by %s\n"), + hex, signature_check.signer); + + free(signature_check.gpg_output); + free(signature_check.gpg_status); + free(signature_check.signer); + free(signature_check.key); + } + } + strbuf_addstr(&buf, "merge"); for (p = remoteheads; p; p = p->next) strbuf_addf(&buf, " %s", merge_remote_util(p->item)->name);