@ -14,7 +14,8 @@
#include "diff.h"
#include "diff.h"
#include "revision.h"
#include "revision.h"
#include "rerere.h"
#include "rerere.h"
#include "merge-recursive.h"
#include "merge-ort.h"
#include "merge-ort-wrappers.h"
#include "refs.h"
#include "refs.h"
#include "strvec.h"
#include "strvec.h"
#include "quote.h"
#include "quote.h"
@ -204,6 +205,20 @@ static int git_sequencer_config(const char *k, const char *v, void *cb)
return 0;
return 0;
}
}
if (!opts->default_strategy && !strcmp(k, "pull.twohead")) {
int ret = git_config_string((const char**)&opts->default_strategy, k, v);
if (ret == 0) {
/*
* pull.twohead is allowed to be multi-valued; we only
* care about the first value.
*/
char *tmp = strchr(opts->default_strategy, ' ');
if (tmp)
*tmp = '\0';
}
return ret;
}
status = git_gpg_config(k, v, NULL);
status = git_gpg_config(k, v, NULL);
if (status)
if (status)
return status;
return status;
@ -317,6 +332,7 @@ int sequencer_remove_state(struct replay_opts *opts)
free(opts->committer_name);
free(opts->committer_name);
free(opts->committer_email);
free(opts->committer_email);
free(opts->gpg_sign);
free(opts->gpg_sign);
free(opts->default_strategy);
free(opts->strategy);
free(opts->strategy);
for (i = 0; i < opts->xopts_nr; i++)
for (i = 0; i < opts->xopts_nr; i++)
free(opts->xopts[i]);
free(opts->xopts[i]);
@ -595,8 +611,9 @@ static int do_recursive_merge(struct repository *r,
struct replay_opts *opts)
struct replay_opts *opts)
{
{
struct merge_options o;
struct merge_options o;
struct merge_result result;
struct tree *next_tree, *base_tree, *head_tree;
struct tree *next_tree, *base_tree, *head_tree;
int clean;
int clean, show_output;
int i;
int i;
struct lock_file index_lock = LOCK_INIT;
struct lock_file index_lock = LOCK_INIT;
@ -620,12 +637,27 @@ static int do_recursive_merge(struct repository *r,
for (i = 0; i < opts->xopts_nr; i++)
for (i = 0; i < opts->xopts_nr; i++)
parse_merge_opt(&o, opts->xopts[i]);
parse_merge_opt(&o, opts->xopts[i]);
clean = merge_trees(&o,
if (opts->strategy && !strcmp(opts->strategy, "ort")) {
head_tree,
memset(&result, 0, sizeof(result));
next_tree, base_tree);
merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree,
if (is_rebase_i(opts) && clean <= 0)
&result);
fputs(o.obuf.buf, stdout);
show_output = !is_rebase_i(opts) || !result.clean;
strbuf_release(&o.obuf);
/*
* TODO: merge_switch_to_result will update index/working tree;
* we only really want to do that if !result.clean || this is
* the final patch to be picked. But determining this is the
* final patch would take some work, and "head_tree" would need
* to be replace with the tree the index matched before we
* started doing any picks.
*/
merge_switch_to_result(&o, head_tree, &result, 1, show_output);
clean = result.clean;
} else {
clean = merge_trees(&o, head_tree, next_tree, base_tree);
if (is_rebase_i(opts) && clean <= 0)
fputs(o.obuf.buf, stdout);
strbuf_release(&o.obuf);
}
if (clean < 0) {
if (clean < 0) {
rollback_lock_file(&index_lock);
rollback_lock_file(&index_lock);
return clean;
return clean;
@ -1991,7 +2023,10 @@ static int do_pick_commit(struct repository *r,
if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
res = -1;
res = -1;
else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
else if (!opts->strategy ||
!strcmp(opts->strategy, "recursive") ||
!strcmp(opts->strategy, "ort") ||
command == TODO_REVERT) {
res = do_recursive_merge(r, base, next, base_label, next_label,
res = do_recursive_merge(r, base, next, base_label, next_label,
&head, &msgbuf, opts);
&head, &msgbuf, opts);
if (res < 0)
if (res < 0)
@ -3485,7 +3520,9 @@ static int do_merge(struct repository *r,
struct commit_list *bases, *j, *reversed = NULL;
struct commit_list *bases, *j, *reversed = NULL;
struct commit_list *to_merge = NULL, **tail = &to_merge;
struct commit_list *to_merge = NULL, **tail = &to_merge;
const char *strategy = !opts->xopts_nr &&
const char *strategy = !opts->xopts_nr &&
(!opts->strategy || !strcmp(opts->strategy, "recursive")) ?
(!opts->strategy ||
!strcmp(opts->strategy, "recursive") ||
!strcmp(opts->strategy, "ort")) ?
NULL : opts->strategy;
NULL : opts->strategy;
struct merge_options o;
struct merge_options o;
int merge_arg_len, oneline_offset, can_fast_forward, ret, k;
int merge_arg_len, oneline_offset, can_fast_forward, ret, k;
@ -3722,7 +3759,20 @@ static int do_merge(struct repository *r,
o.branch2 = ref_name.buf;
o.branch2 = ref_name.buf;
o.buffer_output = 2;
o.buffer_output = 2;
ret = merge_recursive(&o, head_commit, merge_commit, reversed, &i);
if (opts->strategy && !strcmp(opts->strategy, "ort")) {
/*
* TODO: Should use merge_incore_recursive() and
* merge_switch_to_result(), skipping the call to
* merge_switch_to_result() when we don't actually need to
* update the index and working copy immediately.
*/
ret = merge_ort_recursive(&o,
head_commit, merge_commit, reversed,
&i);
} else {
ret = merge_recursive(&o, head_commit, merge_commit, reversed,
&i);
}
if (ret <= 0)
if (ret <= 0)
fputs(o.obuf.buf, stdout);
fputs(o.obuf.buf, stdout);
strbuf_release(&o.obuf);
strbuf_release(&o.obuf);