Commit db3462ce7714e2a6ce23130a7046a77860739e05

Edward Thomson 2014-01-19T22:36:50

Support union merges

diff --git a/include/git2/merge.h b/include/git2/merge.h
index c079ef9..ad9b5e2 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -43,6 +43,9 @@ typedef enum {
 
 	/* Produce a file containing the "theirs" side of conflicting regions. */
 	GIT_MERGE_FILE_FAVOR_THEIRS = 2,
+
+	/* Produce a file blending the sides in a union of conflicting regions */
+	GIT_MERGE_FILE_FAVOR_UNION = 3,
 } git_merge_file_favor_t;
 
 
diff --git a/src/merge_file.c b/src/merge_file.c
index fb0e299..9961ef2 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -156,6 +156,8 @@ int git_merge_files(
 		xmparam.favor = XDL_MERGE_FAVOR_OURS;
 	else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_THEIRS)
 		xmparam.favor = XDL_MERGE_FAVOR_THEIRS;
+	else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_UNION)
+		xmparam.favor = XDL_MERGE_FAVOR_UNION;
 
 	xmparam.level = 
 		(opts && (opts->flags & GIT_MERGE_FILE_SIMPLIFY_ALNUM)) ?
diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c
index 757e20c..6b152cc 100644
--- a/tests/merge/workdir/simple.c
+++ b/tests/merge/workdir/simple.c
@@ -109,6 +109,10 @@ static git_index *repo_index;
 	"this file is changed in branch and master\n" \
 	">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
 
+#define CONFLICTING_UNION_FILE \
+	"this file is changed in master and branch\n" \
+	"this file is changed in branch and master\n"
+
 // Fixture setup and teardown
 void test_merge_workdir_simple__initialize(void)
 {
@@ -329,6 +333,45 @@ void test_merge_workdir_simple__diff3(void)
 	git_merge_result_free(result);
 }
 
+void test_merge_workdir_simple__union(void)
+{
+	git_merge_result *result;
+	git_buf conflicting_buf = GIT_BUF_INIT;
+
+	struct merge_index_entry merge_index_entries[] = {
+		ADDED_IN_MASTER_INDEX_ENTRY,
+		AUTOMERGEABLE_INDEX_ENTRY,
+		CHANGED_IN_BRANCH_INDEX_ENTRY,
+		CHANGED_IN_MASTER_INDEX_ENTRY,
+
+		{ 0100644, "72cdb057b340205164478565e91eb71647e66891", 0, "conflicting.txt" },
+
+		UNCHANGED_INDEX_ENTRY,
+	};
+
+	struct merge_reuc_entry merge_reuc_entries[] = {
+		AUTOMERGEABLE_REUC_ENTRY,
+		CONFLICTING_REUC_ENTRY,
+		REMOVED_IN_BRANCH_REUC_ENTRY,
+		REMOVED_IN_MASTER_REUC_ENTRY
+	};
+
+	set_core_autocrlf_to(repo, false);
+
+	cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_UNION, 0));
+	cl_assert(!git_merge_result_is_fastforward(result));
+
+	cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+		TEST_REPO_PATH "/conflicting.txt"));
+	cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_UNION_FILE) == 0);
+	git_buf_free(&conflicting_buf);
+
+	cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
+	cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
+
+	git_merge_result_free(result);
+}
+
 void test_merge_workdir_simple__diff3_from_config(void)
 {
 	git_merge_result *result;