Merge branch 'jc/pull-signed-tag'
[git/git.git] / builtin / merge.c
index 3fc5492..7349396 100644 (file)
@@ -409,20 +409,10 @@ static void finish(struct commit *head_commit,
        strbuf_release(&reflog_message);
 }
 
-static struct object *want_commit(const char *name)
-{
-       struct object *obj;
-       unsigned char sha1[20];
-       if (get_sha1(name, sha1))
-               return NULL;
-       obj = parse_object(sha1);
-       return peel_to_type(name, 0, obj, OBJ_COMMIT);
-}
-
 /* Get the name for the merge commit's message. */
 static void merge_name(const char *remote, struct strbuf *msg)
 {
-       struct object *remote_head;
+       struct commit *remote_head;
        unsigned char branch_head[20], buf_sha[20];
        struct strbuf buf = STRBUF_INIT;
        struct strbuf bname = STRBUF_INIT;
@@ -434,7 +424,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
        remote = bname.buf;
 
        memset(branch_head, 0, sizeof(branch_head));
-       remote_head = want_commit(remote);
+       remote_head = get_merge_parent(remote);
        if (!remote_head)
                die(_("'%s' does not point to a commit"), remote);
 
@@ -444,6 +434,11 @@ static void merge_name(const char *remote, struct strbuf *msg)
                                    sha1_to_hex(branch_head), remote);
                        goto cleanup;
                }
+               if (!prefixcmp(found_ref, "refs/tags/")) {
+                       strbuf_addf(msg, "%s\t\ttag '%s' of .\n",
+                                   sha1_to_hex(branch_head), remote);
+                       goto cleanup;
+               }
                if (!prefixcmp(found_ref, "refs/remotes/")) {
                        strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n",
                                    sha1_to_hex(branch_head), remote);
@@ -485,7 +480,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
                if (resolve_ref(truname.buf, buf_sha, 1, NULL)) {
                        strbuf_addf(msg,
                                    "%s\t\tbranch '%s'%s of .\n",
-                                   sha1_to_hex(remote_head->sha1),
+                                   sha1_to_hex(remote_head->object.sha1),
                                    truname.buf + 11,
                                    (early ? " (early part)" : ""));
                        strbuf_release(&truname);
@@ -515,7 +510,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
                goto cleanup;
        }
        strbuf_addf(msg, "%s\t\tcommit '%s'\n",
-               sha1_to_hex(remote_head->sha1), remote);
+               sha1_to_hex(remote_head->object.sha1), remote);
 cleanup:
        strbuf_release(&buf);
        strbuf_release(&bname);
@@ -716,7 +711,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
                                die(_("Unknown option for merge-recursive: -X%s"), xopts[x]);
 
                o.branch1 = head_arg;
-               o.branch2 = remoteheads->item->util;
+               o.branch2 = merge_remote_util(remoteheads->item)->name;
 
                for (j = common; j; j = j->next)
                        commit_list_insert(j->item, &reversed);
@@ -1056,9 +1051,16 @@ static void write_merge_state(void)
        struct commit_list *j;
        struct strbuf buf = STRBUF_INIT;
 
-       for (j = remoteheads; j; j = j->next)
-               strbuf_addf(&buf, "%s\n",
-                       sha1_to_hex(j->item->object.sha1));
+       for (j = remoteheads; j; j = j->next) {
+               unsigned const char *sha1;
+               struct commit *c = j->item;
+               if (c->util && merge_remote_util(c)->obj) {
+                       sha1 = merge_remote_util(c)->obj->sha1;
+               } else {
+                       sha1 = c->object.sha1;
+               }
+               strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
+       }
        filename = git_path("MERGE_HEAD");
        fd = open(filename, O_WRONLY | O_CREAT, 0666);
        if (fd < 0)
@@ -1197,7 +1199,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                argv += 2;
                argc -= 2;
        } else if (!head_commit) {
-               struct object *remote_head;
+               struct commit *remote_head;
                /*
                 * If the merged head is a valid one there is no reason
                 * to forbid "git merge" into a branch yet to be born.
@@ -1211,12 +1213,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                if (!allow_fast_forward)
                        die(_("Non-fast-forward commit does not make sense into "
                            "an empty head"));
-               remote_head = want_commit(argv[0]);
+               remote_head = get_merge_parent(argv[0]);
                if (!remote_head)
                        die(_("%s - not something we can merge"), argv[0]);
-               read_empty(remote_head->sha1, 0);
-               update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0,
-                               DIE_ON_ERR);
+               read_empty(remote_head->object.sha1, 0);
+               update_ref("initial pull", "HEAD", remote_head->object.sha1,
+                          NULL, 0, DIE_ON_ERR);
                return 0;
        } else {
                struct strbuf merge_names = STRBUF_INIT;
@@ -1225,19 +1227,20 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                head_arg = "HEAD";
 
                /*
-                * All the rest are the commits being merged;
-                * prepare the standard merge summary message to
-                * be appended to the given message.  If remote
-                * is invalid we will die later in the common
-                * codepath so we discard the error in this
-                * loop.
+                * All the rest are the commits being merged; prepare
+                * the standard merge summary message to be appended
+                * to the given message.
                 */
                for (i = 0; i < argc; i++)
                        merge_name(argv[i], &merge_names);
 
                if (!have_message || shortlog_len) {
-                       fmt_merge_msg(&merge_names, &merge_msg, !have_message,
-                                     shortlog_len);
+                       struct fmt_merge_msg_opts opts;
+                       memset(&opts, 0, sizeof(opts));
+                       opts.add_title = !have_message;
+                       opts.shortlog_len = shortlog_len;
+
+                       fmt_merge_msg(&merge_names, &merge_msg, &opts);
                        if (merge_msg.len)
                                strbuf_setlen(&merge_msg, merge_msg.len - 1);
                }
@@ -1254,19 +1257,20 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        strbuf_reset(&buf);
 
        for (i = 0; i < argc; i++) {
-               struct object *o;
-               struct commit *commit;
-
-               o = want_commit(argv[i]);
-               if (!o)
+               struct commit *commit = get_merge_parent(argv[i]);
+               if (!commit)
                        die(_("%s - not something we can merge"), argv[i]);
-               commit = lookup_commit(o->sha1);
-               commit->util = (void *)argv[i];
                remotes = &commit_list_insert(commit, remotes)->next;
-
-               strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
+               strbuf_addf(&buf, "GITHEAD_%s",
+                           sha1_to_hex(commit->object.sha1));
                setenv(buf.buf, argv[i], 1);
                strbuf_reset(&buf);
+               if (merge_remote_util(commit) &&
+                   merge_remote_util(commit)->obj &&
+                   merge_remote_util(commit)->obj->type == OBJ_TAG) {
+                       option_edit = 1;
+                       allow_fast_forward = 0;
+               }
        }
 
        if (!use_strategies) {
@@ -1310,7 +1314,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        !hashcmp(common->item->object.sha1, head_commit->object.sha1)) {
                /* Again the most common case of merging one remote. */
                struct strbuf msg = STRBUF_INIT;
-               struct object *o;
+               struct commit *commit;
                char hex[41];
 
                strcpy(hex, find_unique_abbrev(head_commit->object.sha1, DEFAULT_ABBREV));
@@ -1324,14 +1328,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                if (have_message)
                        strbuf_addstr(&msg,
                                " (no commit created; -m option ignored)");
-               o = want_commit(sha1_to_hex(remoteheads->item->object.sha1));
-               if (!o)
+               commit = remoteheads->item;
+               if (!commit)
                        return 1;
 
-               if (checkout_fast_forward(head_commit->object.sha1, remoteheads->item->object.sha1))
+               if (checkout_fast_forward(head_commit->object.sha1,
+                                         commit->object.sha1))
                        return 1;
 
-               finish(head_commit, o->sha1, msg.buf);
+               finish(head_commit, commit->object.sha1, msg.buf);
                drop_save();
                return 0;
        } else if (!remoteheads->next && common->next)