diff options
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/merge.c | 106 |
1 files changed, 72 insertions, 34 deletions
diff --git a/builtin/merge.c b/builtin/merge.c index eb3be6817e..42f9fcc174 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -505,28 +505,6 @@ static void merge_name(const char *remote, struct strbuf *msg) strbuf_release(&truname); } - if (!strcmp(remote, "FETCH_HEAD") && - !access(git_path("FETCH_HEAD"), R_OK)) { - const char *filename; - FILE *fp; - struct strbuf line = STRBUF_INIT; - char *ptr; - - filename = git_path("FETCH_HEAD"); - fp = fopen(filename, "r"); - if (!fp) - die_errno(_("could not open '%s' for reading"), - filename); - strbuf_getline(&line, fp, '\n'); - fclose(fp); - ptr = strstr(line.buf, "\tnot-for-merge\t"); - if (ptr) - strbuf_remove(&line, ptr-line.buf+1, 13); - strbuf_addbuf(msg, &line); - strbuf_release(&line); - goto cleanup; - } - if (remote_head->util) { struct merge_remote_desc *desc; desc = merge_remote_util(remote_head); @@ -1090,6 +1068,60 @@ static void prepare_merge_message(struct strbuf *merge_names, struct strbuf *mer strbuf_setlen(merge_msg, merge_msg->len - 1); } +static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge_names) +{ + const char *filename; + int fd, pos, npos; + struct strbuf fetch_head_file = STRBUF_INIT; + + if (!merge_names) + merge_names = &fetch_head_file; + + filename = git_path("FETCH_HEAD"); + fd = open(filename, O_RDONLY); + if (fd < 0) + die_errno(_("could not open '%s' for reading"), filename); + + if (strbuf_read(merge_names, fd, 0) < 0) + die_errno(_("could not read '%s'"), filename); + if (close(fd) < 0) + die_errno(_("could not close '%s'"), filename); + + for (pos = 0; pos < merge_names->len; pos = npos) { + unsigned char sha1[20]; + char *ptr; + struct commit *commit; + + ptr = strchr(merge_names->buf + pos, '\n'); + if (ptr) + npos = ptr - merge_names->buf + 1; + else + npos = merge_names->len; + + if (npos - pos < 40 + 2 || + get_sha1_hex(merge_names->buf + pos, sha1)) + commit = NULL; /* bad */ + else if (memcmp(merge_names->buf + pos + 40, "\t\t", 2)) + continue; /* not-for-merge */ + else { + char saved = merge_names->buf[pos + 40]; + merge_names->buf[pos + 40] = '\0'; + commit = get_merge_parent(merge_names->buf + pos); + merge_names->buf[pos + 40] = saved; + } + if (!commit) { + if (ptr) + *ptr = '\0'; + die("not something we can merge in %s: %s", + filename, merge_names->buf + pos); + } + remotes = &commit_list_insert(commit, remotes)->next; + } + + if (merge_names == &fetch_head_file) + strbuf_release(&fetch_head_file); +} + static struct commit_list *collect_parents(struct commit *head_commit, int *head_subsumed, int argc, const char **argv, @@ -1105,21 +1137,27 @@ static struct commit_list *collect_parents(struct commit *head_commit, if (head_commit) remotes = &commit_list_insert(head_commit, remotes)->next; - for (i = 0; i < argc; i++) { - struct commit *commit = get_merge_parent(argv[i]); - if (!commit) - help_unknown_ref(argv[i], "merge", - "not something we can merge"); - remotes = &commit_list_insert(commit, remotes)->next; - } - remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads); + if (argc == 1 && !strcmp(argv[0], "FETCH_HEAD")) { + handle_fetch_head(remotes, autogen); + remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads); + } else { + for (i = 0; i < argc; i++) { + struct commit *commit = get_merge_parent(argv[i]); + if (!commit) + help_unknown_ref(argv[i], "merge", + "not something we can merge"); + remotes = &commit_list_insert(commit, remotes)->next; + } + remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads); + if (autogen) { + struct commit_list *p; + for (p = remoteheads; p; p = p->next) + merge_name(merge_remote_util(p->item)->name, autogen); + } + } if (autogen) { - struct commit_list *p; - for (p = remoteheads; p; p = p->next) - merge_name(merge_remote_util(p->item)->name, autogen); - prepare_merge_message(autogen, merge_msg); strbuf_release(autogen); } |