summaryrefslogtreecommitdiff
path: root/xdiff
diff options
context:
space:
mode:
authorLibravatar Johannes Schindelin <Johannes.Schindelin@gmx.de>2008-02-17 19:07:40 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2008-02-18 00:10:37 -0800
commitee95ec5d58d536243966de6ee810d345074b755e (patch)
tree082c2b30fd7042e81f1e0398d79d829a0d8c4a61 /xdiff
parentxdl_merge(): make XDL_MERGE_ZEALOUS output simpler (diff)
downloadtgif-ee95ec5d58d536243966de6ee810d345074b755e.tar.xz
xdl_merge(): introduce XDL_MERGE_ZEALOUS_ALNUM
When a merge conflicts, there are often common lines that are not really common, such as empty lines or lines containing a single curly bracket. With XDL_MERGE_ZEALOUS_ALNUM, we use the following heuristics: when a hunk does not contain any letters or digits, it is treated as conflicting. In other words, a conflict which used to look like this: <<<<<<< a = 1; ======= output(); >>>>>>> } } } <<<<<<< output(); ======= b = 1; >>>>>>> will look like this with ZEALOUS_ALNUM: <<<<<<< a = 1; } } } output(); ======= output(); } } } b = 1; >>>>>>> To demonstrate this, git-merge-file has been switched from XDL_MERGE_ZEALOUS to XDL_MERGE_ZEALOUS_ALNUM. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'xdiff')
-rw-r--r--xdiff/xdiff.h1
-rw-r--r--xdiff/xmerge.c31
2 files changed, 28 insertions, 4 deletions
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index c00ddaa6e9..413082e1fd 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -53,6 +53,7 @@ extern "C" {
#define XDL_MERGE_MINIMAL 0
#define XDL_MERGE_EAGER 1
#define XDL_MERGE_ZEALOUS 2
+#define XDL_MERGE_ZEALOUS_ALNUM 3
typedef struct s_mmfile {
char *ptr;
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index ecbdae502c..82b3573e7a 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -248,6 +248,23 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
return 0;
}
+static int line_contains_alnum(const char *ptr, long size)
+{
+ while (size--)
+ if (isalnum(*(ptr++)))
+ return 1;
+ return 0;
+}
+
+static int lines_contain_alnum(xdfenv_t *xe, int i, int chg)
+{
+ for (; chg; chg--, i++)
+ if (line_contains_alnum(xe->xdf2.recs[i]->ptr,
+ xe->xdf2.recs[i]->size))
+ return 1;
+ return 0;
+}
+
/*
* This function merges m and m->next, marking everything between those hunks
* as conflicting, too.
@@ -266,7 +283,8 @@ static void xdl_merge_two_conflicts(xdmerge_t *m)
* it appears simpler -- because it takes up less (or as many) lines --
* if the lines are moved into the conflicts.
*/
-static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m)
+static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
+ int simplify_if_no_alnum)
{
int result = 0;
@@ -282,9 +300,12 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m)
begin = m->i1 + m->chg1;
end = next_m->i1;
- if (m->mode != 0 || next_m->mode != 0 || end - begin > 3)
+ if (m->mode != 0 || next_m->mode != 0 ||
+ (end - begin > 3 &&
+ (!simplify_if_no_alnum ||
+ lines_contain_alnum(xe1, begin, end - begin)))) {
m = next_m;
- else {
+ } else {
result++;
xdl_merge_two_conflicts(m);
}
@@ -295,6 +316,8 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m)
* level == 0: mark all overlapping changes as conflict
* level == 1: mark overlapping changes as conflict only if not identical
* level == 2: analyze non-identical changes for minimal conflict set
+ * level == 3: analyze non-identical changes for minimal conflict set, but
+ * treat hunks not containing any letter or number as conflicting
*
* returns < 0 on error, == 0 for no conflicts, else number of conflicts
*/
@@ -400,7 +423,7 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
/* refine conflicts */
if (level > 1 &&
(xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
- xdl_simplify_non_conflicts(xe1, changes) < 0)) {
+ xdl_simplify_non_conflicts(xe1, changes, level > 2) < 0)) {
xdl_cleanup_merge(changes);
return -1;
}