Merge branch 'jk/fetch-always-update-tracking'
[gitweb.git] / builtin / merge.c
index 0d94d89e7409c625fd2a15f65205a45d4a6d2b89..2ebe732896c1b3bfd920941b5182b793468c0afe 100644 (file)
@@ -49,7 +49,7 @@ static const char * const builtin_merge_usage[] = {
 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 @@ static struct option builtin_merge_options[] = {
        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"),
@@ -1052,7 +1054,8 @@ static struct commit_list *collect_parents(struct commit *head_commit,
        for (i = 0; i < argc; i++) {
                struct commit *commit = get_merge_parent(argv[i]);
                if (!commit)
-                       die(_("%s - not something we can merge"), argv[i]);
+                       help_unknown_ref(argv[i], "merge",
+                                        "not something we can merge");
                remotes = &commit_list_insert(commit, remotes)->next;
        }
        *remotes = NULL;
@@ -1246,6 +1249,39 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                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);