static int try_merge_strategy(const char *strategy, struct commit_list *common, const char *head_arg) { int index_fd; struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); index_fd = hold_locked_index(lock, 1); refresh_cache(REFRESH_QUIET); if (active_cache_changed && (write_cache(index_fd, active_cache, active_nr) || commit_locked_index(lock))) return error(_("Unable to write index.")); rollback_lock_file(lock); if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) { int clean, x; struct commit *result; struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); int index_fd; struct commit_list *reversed = NULL; struct merge_options o; struct commit_list *j; if (remoteheads->next) { error(_("Not handling anything other than two heads merge.")); return 2; } init_merge_options(&o); if (!strcmp(strategy, "subtree")) o.subtree_shift = ""; o.renormalize = option_renormalize; o.show_rename_progress = show_progress == -1 ? isatty(2) : show_progress; for (x = 0; x < xopts_nr; x++) if (parse_merge_opt(&o, xopts[x])) die(_("Unknown option for merge-recursive: -X%s"), xopts[x]); o.branch1 = head_arg; o.branch2 = remoteheads->item->util; for (j = common; j; j = j->next) commit_list_insert(j->item, &reversed); index_fd = hold_locked_index(lock, 1); clean = merge_recursive(&o, lookup_commit(head), remoteheads->item, reversed, &result); if (active_cache_changed && (write_cache(index_fd, active_cache, active_nr) || commit_locked_index(lock))) die (_("unable to write %s"), get_index_file()); rollback_lock_file(lock); return clean ? 0 : 1; } else { return try_merge_command(strategy, xopts_nr, xopts, common, head_arg, remoteheads); } }
int cmd_merge_recursive(int argc, const char **argv, const char *prefix) { const unsigned char *bases[21]; unsigned bases_count = 0; int i, failed; unsigned char h1[20], h2[20]; struct merge_options o; struct commit *result; init_merge_options(&o); if (argv[0] && ends_with(argv[0], "-subtree")) o.subtree_shift = ""; if (argc < 4) usagef(builtin_merge_recursive_usage, argv[0]); for (i = 1; i < argc; ++i) { const char *arg = argv[i]; if (starts_with(arg, "--")) { if (!arg[2]) break; if (parse_merge_opt(&o, arg + 2)) die("Unknown option %s", arg); continue; } if (bases_count < ARRAY_SIZE(bases)-1) { unsigned char *sha = xmalloc(20); if (get_sha1(argv[i], sha)) die("Could not parse object '%s'", argv[i]); bases[bases_count++] = sha; } else warning("Cannot handle more than %d bases. " "Ignoring %s.", (int)ARRAY_SIZE(bases)-1, argv[i]); } if (argc - i != 3) /* "--" "<head>" "<remote>" */ die("Not handling anything other than two heads merge."); o.branch1 = argv[++i]; o.branch2 = argv[++i]; if (get_sha1(o.branch1, h1)) die("Could not resolve ref '%s'", o.branch1); if (get_sha1(o.branch2, h2)) die("Could not resolve ref '%s'", o.branch2); o.branch1 = better_branch_name(o.branch1); o.branch2 = better_branch_name(o.branch2); if (o.verbosity >= 3) printf("Merging %s with %s\n", o.branch1, o.branch2); failed = merge_recursive_generic(&o, h1, h2, bases_count, bases, &result); if (failed < 0) return 128; /* die() error code */ return failed; }
static int do_recursive_merge(struct commit *base, struct commit *next, const char *base_label, const char *next_label, unsigned char *head, struct strbuf *msgbuf, struct replay_opts *opts) { struct merge_options o; struct tree *result, *next_tree, *base_tree, *head_tree; int clean, index_fd; const char **xopt; static struct lock_file index_lock; index_fd = hold_locked_index(&index_lock, 1); read_cache(); init_merge_options(&o); o.ancestor = base ? base_label : "(empty tree)"; o.branch1 = "HEAD"; o.branch2 = next ? next_label : "(empty tree)"; head_tree = parse_tree_indirect(head); next_tree = next ? next->tree : empty_tree(); base_tree = base ? base->tree : empty_tree(); for (xopt = opts->xopts; xopt != opts->xopts + opts->xopts_nr; xopt++) parse_merge_opt(&o, *xopt); clean = merge_trees(&o, head_tree, next_tree, base_tree, &result); if (active_cache_changed && (write_cache(index_fd, active_cache, active_nr) || commit_locked_index(&index_lock))) /* TRANSLATORS: %s will be "revert" or "cherry-pick" */ die(_("%s: Unable to write new index file"), action_name(opts)); rollback_lock_file(&index_lock); if (opts->signoff) append_signoff(msgbuf, 0, 0); if (!clean) { int i; strbuf_addstr(msgbuf, "\nConflicts:\n"); for (i = 0; i < active_nr;) { const struct cache_entry *ce = active_cache[i++]; if (ce_stage(ce)) { strbuf_addch(msgbuf, '\t'); strbuf_addstr(msgbuf, ce->name); strbuf_addch(msgbuf, '\n'); while (i < active_nr && !strcmp(ce->name, active_cache[i]->name)) i++; } } } return !clean; }
static int do_recursive_merge(struct commit *base, struct commit *next, const char *base_label, const char *next_label, unsigned char *head, struct strbuf *msgbuf, struct replay_opts *opts) { struct merge_options o; struct tree *result, *next_tree, *base_tree, *head_tree; int clean; char **xopt; static struct lock_file index_lock; hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); read_cache(); init_merge_options(&o); o.ancestor = base ? base_label : "(empty tree)"; o.branch1 = "HEAD"; o.branch2 = next ? next_label : "(empty tree)"; head_tree = parse_tree_indirect(head); next_tree = next ? next->tree : empty_tree(); base_tree = base ? base->tree : empty_tree(); for (xopt = opts->xopts; xopt != opts->xopts + opts->xopts_nr; xopt++) parse_merge_opt(&o, *xopt); clean = merge_trees(&o, head_tree, next_tree, base_tree, &result); strbuf_release(&o.obuf); if (clean < 0) return clean; if (active_cache_changed && write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) /* TRANSLATORS: %s will be "revert" or "cherry-pick" */ return error(_("%s: Unable to write new index file"), _(action_name(opts))); rollback_lock_file(&index_lock); if (opts->signoff) append_signoff(msgbuf, 0, 0); if (!clean) append_conflicts_hint(msgbuf); return !clean; }