Commit 8683d31f by Edward Thomson

merge: add GIT_MERGE_TREE_FAIL_ON_CONFLICT

Provide a new merge option, GIT_MERGE_TREE_FAIL_ON_CONFLICT, which
will stop on the first conflict and fail the merge operation with
GIT_EMERGECONFLICT.
parent dc2cf3eb
......@@ -49,6 +49,7 @@ typedef enum {
GIT_EINVALID = -21, /**< Invalid operation or input */
GIT_EUNCOMMITTED = -22, /**< Uncommitted changes in index prevented operation */
GIT_EDIRECTORY = -23, /**< The operation is not valid for a directory */
GIT_EMERGECONFLICT = -24, /**< A merge conflict exists and cannot continue */
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
......
......@@ -72,6 +72,13 @@ typedef enum {
* the ability to merge between a modified and renamed file.
*/
GIT_MERGE_TREE_FIND_RENAMES = (1 << 0),
/**
* If a conflict occurs, exit immediately instead of attempting to
* continue resolving conflicts. The merge operation will fail with
* GIT_EMERGECONFLICT and no index will be returned.
*/
GIT_MERGE_TREE_FAIL_ON_CONFLICT = (1 << 1),
} git_merge_tree_flag_t;
/**
......
......@@ -1701,8 +1701,15 @@ int git_merge__iterators(
if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor, opts.file_flags)) < 0)
goto done;
if (!resolved)
if (!resolved) {
if ((opts.tree_flags & GIT_MERGE_TREE_FAIL_ON_CONFLICT)) {
giterr_set(GITERR_MERGE, "merge conflicts exist");
error = GIT_EMERGECONFLICT;
goto done;
}
git_vector_insert(&diff_list->conflicts, conflict);
}
}
if (!given_opts || !given_opts->metric)
......
......@@ -40,7 +40,7 @@ int merge_trees_from_branches(
cl_git_pass(git_commit_tree(&our_tree, our_commit));
cl_git_pass(git_commit_tree(&their_tree, their_commit));
cl_git_pass(git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, opts));
error = git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, opts);
git_buf_free(&branch_buf);
git_tree_free(our_tree);
......@@ -50,7 +50,7 @@ int merge_trees_from_branches(
git_commit_free(their_commit);
git_commit_free(ancestor_commit);
return 0;
return error;
}
int merge_commits_from_branches(
......@@ -61,6 +61,7 @@ int merge_commits_from_branches(
git_commit *our_commit, *their_commit;
git_oid our_oid, their_oid;
git_buf branch_buf = GIT_BUF_INIT;
int error;
git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name);
cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
......@@ -71,13 +72,13 @@ int merge_commits_from_branches(
cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr));
cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid));
cl_git_pass(git_merge_commits(index, repo, our_commit, their_commit, opts));
error = git_merge_commits(index, repo, our_commit, their_commit, opts);
git_buf_free(&branch_buf);
git_commit_free(our_commit);
git_commit_free(their_commit);
return 0;
return error;
}
int merge_branches(git_repository *repo,
......
......@@ -94,7 +94,6 @@ void test_merge_trees_commits__no_ancestor(void)
git_index_free(index);
}
void test_merge_trees_commits__df_conflict(void)
{
git_index *index;
......@@ -129,3 +128,20 @@ void test_merge_trees_commits__df_conflict(void)
git_index_free(index);
}
void test_merge_trees_commits__fail_on_conflict(void)
{
git_index *index;
git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
opts.tree_flags |= GIT_MERGE_TREE_FAIL_ON_CONFLICT;
cl_git_fail_with(GIT_EMERGECONFLICT,
merge_trees_from_branches(&index, repo, "df_side1", "df_side2", &opts));
cl_git_fail_with(GIT_EMERGECONFLICT,
merge_commits_from_branches(&index, repo, "master", "unrelated", &opts));
cl_git_fail_with(GIT_EMERGECONFLICT,
merge_commits_from_branches(&index, repo, "master", "branch", &opts));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment