Commit 45a86bbfd028a545a71d3e1ea5518d467be8b5aa

Jacques Germishuys 2015-03-09T17:02:52

Allow for merges with whitespace discrepancies

diff --git a/include/git2/merge.h b/include/git2/merge.h
index 40330d0..73375b3 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -111,6 +111,23 @@ typedef enum {
 } git_merge_file_favor_t;
 
 /**
+ * Whitespace merging flags
+ */
+typedef enum {
+	/** Defaults */
+	GIT_MERGE_FILE_IGNORE_DEFAULT = 0,
+
+	/** Ignore all whitespace */
+	GIT_MERGE_FILE_IGNORE_WHITESPACE = (1 << 0),
+
+	/** Ignore changes in amount of whitespace */
+	GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE = (1 << 1),
+
+	/** Ignore whitespace at end of line */
+	GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL = (1 << 2),
+} git_merge_file_whitespace_t;
+
+/**
  * File merging flags
  */
 typedef enum {
@@ -156,6 +173,9 @@ typedef struct {
 
 	/** Merge file flags. */
 	git_merge_file_flags_t flags;
+
+	/** Whitespace merge flags */
+	unsigned int whitespace_flags;
 } git_merge_file_options;
 
 #define GIT_MERGE_FILE_OPTIONS_VERSION 1
@@ -230,6 +250,9 @@ typedef struct {
 
 	/** Flags for handling conflicting content. */
 	git_merge_file_favor_t file_favor;
+
+	/** Flags for handling whitespace */
+	unsigned int whitespace_flags;
 } git_merge_options;
 
 #define GIT_MERGE_OPTIONS_VERSION 1
diff --git a/src/merge.c b/src/merge.c
index 75ad091..2972d9f 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -653,7 +653,8 @@ static int merge_conflict_resolve_automerge(
 	int *resolved,
 	git_merge_diff_list *diff_list,
 	const git_merge_diff *conflict,
-	unsigned int merge_file_favor)
+	unsigned int merge_file_favor,
+	unsigned int whitespace_flags)
 {
 	const git_index_entry *ancestor = NULL, *ours = NULL, *theirs = NULL;
 	git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
@@ -708,6 +709,7 @@ static int merge_conflict_resolve_automerge(
 		&conflict->their_entry : NULL;
 
 	opts.favor = merge_file_favor;
+	opts.whitespace_flags = whitespace_flags;
 
 	if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
 		(error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, &opts)) < 0 ||
@@ -741,7 +743,8 @@ static int merge_conflict_resolve(
 	int *out,
 	git_merge_diff_list *diff_list,
 	const git_merge_diff *conflict,
-	unsigned int merge_file_favor)
+	unsigned int merge_file_favor,
+	unsigned int whitespace_flags)
 {
 	int resolved = 0;
 	int error = 0;
@@ -757,7 +760,8 @@ static int merge_conflict_resolve(
 	if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
 		goto done;
 
-	if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, merge_file_favor)) < 0)
+	if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict,
+		merge_file_favor, whitespace_flags)) < 0)
 		goto done;
 
 	*out = resolved;
@@ -1779,7 +1783,7 @@ int git_merge_trees(
 	git_vector_foreach(&changes, i, conflict) {
 		int resolved = 0;
 
-		if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor)) < 0)
+		if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor, opts.whitespace_flags)) < 0)
 			goto done;
 
 		if (!resolved)
diff --git a/src/merge_file.c b/src/merge_file.c
index ff03644..b827ca9 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -151,6 +151,13 @@ static int git_merge_file__from_inputs(
 	if (options.flags & GIT_MERGE_FILE_STYLE_DIFF3)
 		xmparam.style = XDL_MERGE_DIFF3;
 
+	if (options.whitespace_flags & GIT_MERGE_FILE_IGNORE_WHITESPACE)
+		xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE;
+	if (options.whitespace_flags & GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE)
+		xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE_CHANGE;
+	if (options.whitespace_flags & GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL)
+		xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE_AT_EOL;
+
 	if ((xdl_result = xdl_merge(&ancestor_mmfile, &our_mmfile,
 		&their_mmfile, &xmparam, &mmbuffer)) < 0) {
 		giterr_set(GITERR_MERGE, "Failed to merge files.");