summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2014-01-08 18:29:42 -0800
committerEdward Thomson <ethomson@microsoft.com>2014-01-20 17:15:11 -0500
commitc1d648c5c6361edfb1aa85a31656b628672c7616 (patch)
treef611ff05206f2305c82867514f1e7f22b602c7b7 /src
parente49c98e6efaa444ed73ac3b8318a693801f93184 (diff)
downloadlibgit2-c1d648c5c6361edfb1aa85a31656b628672c7616.tar.gz
merge_file should use more aggressive levels
The default merge_file level was XDL_MERGE_MINIMAL, which will produce conflicts where there should not be in the case where both sides were changed identically. Change the defaults to be more aggressive (XDL_MERGE_ZEALOUS) which will more aggressively compress non-conflicts. This matches git.git's defaults. Increase testing around reverting a previously reverted commit to illustrate this problem.
Diffstat (limited to 'src')
-rw-r--r--src/checkout.c3
-rw-r--r--src/merge.c17
-rw-r--r--src/merge_file.c11
-rw-r--r--src/merge_file.h14
4 files changed, 32 insertions, 13 deletions
diff --git a/src/checkout.c b/src/checkout.c
index e642c975e..cc49800a2 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -1626,6 +1626,7 @@ static int checkout_write_merge(
{
git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT;
+ git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
@@ -1662,7 +1663,7 @@ static int checkout_write_merge(
theirs.label = git_buf_cstr(&their_label);
}
- if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, 0)) < 0)
+ if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0)
goto done;
if (result.path == NULL || result.mode == 0) {
diff --git a/src/merge.c b/src/merge.c
index c0be37dd8..3ac9167e3 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -511,8 +511,9 @@ static int merge_conflict_resolve_automerge(
int *resolved,
git_merge_diff_list *diff_list,
const git_merge_diff *conflict,
- unsigned int automerge_flags)
+ unsigned int merge_file_favor)
{
+ git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
@@ -526,9 +527,11 @@ static int merge_conflict_resolve_automerge(
*resolved = 0;
- if (automerge_flags == GIT_MERGE_AUTOMERGE_NONE)
+ if (merge_file_favor == GIT_MERGE_FILE_FAVOR_NO_MERGE)
return 0;
+ merge_file_opts.favor = merge_file_favor;
+
/* Reject D/F conflicts */
if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
return 0;
@@ -552,7 +555,7 @@ static int merge_conflict_resolve_automerge(
(error = git_merge_file_input_from_index_entry(&ancestor, diff_list->repo, &conflict->ancestor_entry)) < 0 ||
(error = git_merge_file_input_from_index_entry(&ours, diff_list->repo, &conflict->our_entry)) < 0 ||
(error = git_merge_file_input_from_index_entry(&theirs, diff_list->repo, &conflict->their_entry)) < 0 ||
- (error = git_merge_files(&result, &ancestor, &ours, &theirs, automerge_flags)) < 0 ||
+ (error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0 ||
!result.automergeable ||
(error = git_odb_write(&automerge_oid, odb, result.data, result.len, GIT_OBJ_BLOB)) < 0)
goto done;
@@ -586,7 +589,7 @@ static int merge_conflict_resolve(
int *out,
git_merge_diff_list *diff_list,
const git_merge_diff *conflict,
- unsigned int automerge_flags)
+ unsigned int merge_file_favor)
{
int resolved = 0;
int error = 0;
@@ -596,14 +599,14 @@ static int merge_conflict_resolve(
if ((error = merge_conflict_resolve_trivial(&resolved, diff_list, conflict)) < 0)
goto done;
- if (automerge_flags != GIT_MERGE_AUTOMERGE_NONE) {
+ if (merge_file_favor != GIT_MERGE_FILE_FAVOR_NO_MERGE) {
if (!resolved && (error = merge_conflict_resolve_one_removed(&resolved, diff_list, conflict)) < 0)
goto done;
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, automerge_flags)) < 0)
+ if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, merge_file_favor)) < 0)
goto done;
}
@@ -1589,7 +1592,7 @@ int git_merge_trees(
git_vector_foreach(&changes, i, conflict) {
int resolved = 0;
- if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.automerge_flags)) < 0)
+ if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor)) < 0)
goto done;
if (!resolved)
diff --git a/src/merge_file.c b/src/merge_file.c
index 48fc46e57..d13190276 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -130,7 +130,7 @@ int git_merge_files(
git_merge_file_input *ancestor,
git_merge_file_input *ours,
git_merge_file_input *theirs,
- git_merge_automerge_flags flags)
+ git_merge_file_options *opts)
{
xmparam_t xmparam;
mmbuffer_t mmbuffer;
@@ -152,12 +152,15 @@ int git_merge_files(
out->path = merge_file_best_path(ancestor, ours, theirs);
out->mode = merge_file_best_mode(ancestor, ours, theirs);
- if (flags == GIT_MERGE_AUTOMERGE_FAVOR_OURS)
+ if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_OURS)
xmparam.favor = XDL_MERGE_FAVOR_OURS;
-
- if (flags == GIT_MERGE_AUTOMERGE_FAVOR_THEIRS)
+ else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_THEIRS)
xmparam.favor = XDL_MERGE_FAVOR_THEIRS;
+ xmparam.level =
+ (opts && (opts->flags & GIT_MERGE_FILE_SIMPLIFY_ALNUM)) ?
+ XDL_MERGE_ZEALOUS_ALNUM : XDL_MERGE_ZEALOUS;
+
if ((xdl_result = xdl_merge(&ancestor->mmfile, &ours->mmfile,
&theirs->mmfile, &xmparam, &mmbuffer)) < 0) {
giterr_set(GITERR_MERGE, "Failed to merge files.");
diff --git a/src/merge_file.h b/src/merge_file.h
index 0af2f0a57..5d7ea9752 100644
--- a/src/merge_file.h
+++ b/src/merge_file.h
@@ -34,6 +34,18 @@ typedef struct {
#define GIT_MERGE_FILE_RESULT_INIT {0}
+typedef enum {
+ /* Condense non-alphanumeric regions for simplified diff file */
+ GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 0),
+} git_merge_file_flags_t;
+
+typedef struct {
+ git_merge_file_favor_t favor;
+ git_merge_file_flags_t flags;
+} git_merge_file_options;
+
+#define GIT_MERGE_FILE_OPTIONS_INIT {0}
+
int git_merge_file_input_from_index_entry(
git_merge_file_input *input,
git_repository *repo,
@@ -49,7 +61,7 @@ int git_merge_files(
git_merge_file_input *ancestor,
git_merge_file_input *ours,
git_merge_file_input *theirs,
- git_merge_automerge_flags flags);
+ git_merge_file_options *opts);
GIT_INLINE(void) git_merge_file_input_free(git_merge_file_input *input)
{