author | Junio C Hamano <gitster@pobox.com> | |
Wed, 27 Feb 2008 19:57:19 +0000 (11:57 -0800) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Wed, 27 Feb 2008 19:57:19 +0000 (11:57 -0800) |
* js/merge:
xdl_merge(): introduce XDL_MERGE_ZEALOUS_ALNUM
xdl_merge(): make XDL_MERGE_ZEALOUS output simpler
xdl_merge(): introduce XDL_MERGE_ZEALOUS_ALNUM
xdl_merge(): make XDL_MERGE_ZEALOUS output simpler
builtin-merge-file.c | patch | blob | history | |
t/t6023-merge-file.sh | patch | blob | history | |
xdiff/xdiff.h | patch | blob | history | |
xdiff/xmerge.c | patch | blob | history |
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 58deb62ac08507901c40e89aec0cea7fcdc78f1e..adce6d4635a4153428368073677cd74a9bafc045 100644 (file)
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
}
ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
- &xpp, XDL_MERGE_ZEALOUS, &result);
+ &xpp, XDL_MERGE_ZEALOUS_ALNUM, &result);
for (i = 0; i < 3; i++)
free(mmfs[i].ptr);
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index 86419964b441ebcc15592b872933915472c463d2..79dc58b2ce962ea133c4796d0dff66eb9684b48a 100755 (executable)
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
grep "Cannot merge binary files" merge.err
'
+sed -e "s/deerit.$/deerit;/" -e "s/me;$/me./" < new5.txt > new6.txt
+sed -e "s/deerit.$/deerit,/" -e "s/me;$/me,/" < new5.txt > new7.txt
+
+test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
+
+ ! git merge-file -p new6.txt new5.txt new7.txt > output &&
+ test 1 = $(grep ======= < output | wc -l)
+
+'
+
+sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit;/" < new6.txt > new8.txt
+sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit --/" < new7.txt > new9.txt
+
+test_expect_success 'ZEALOUS_ALNUM' '
+
+ ! git merge-file -p new8.txt new5.txt new9.txt > merge.out &&
+ test 1 = $(grep ======= < merge.out | wc -l)
+
+'
+
test_done
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index c00ddaa6e987407743d2c8877f9ca6e772f89c86..413082e1fdf537d230a0f58940cee7466b965d0e 100644 (file)
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
#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 b83b3348cc3aab66b13cb565a0a0fabaef4b689b..82b3573e7ada8c6df13ac24a78650b80af91ea73 100644 (file)
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
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.
+ */
+static void xdl_merge_two_conflicts(xdmerge_t *m)
+{
+ xdmerge_t *next_m = m->next;
+ m->chg1 = next_m->i1 + next_m->chg1 - m->i1;
+ m->chg2 = next_m->i2 + next_m->chg2 - m->i2;
+ m->next = next_m->next;
+ free(next_m);
+}
+
+/*
+ * If there are less than 3 non-conflicting lines between conflicts,
+ * 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,
+ int simplify_if_no_alnum)
+{
+ int result = 0;
+
+ if (!m)
+ return result;
+ for (;;) {
+ xdmerge_t *next_m = m->next;
+ int begin, end;
+
+ if (!next_m)
+ return result;
+
+ begin = m->i1 + m->chg1;
+ end = next_m->i1;
+
+ 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 {
+ result++;
+ xdl_merge_two_conflicts(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
*/
if (!changes)
changes = c;
/* refine conflicts */
- if (level > 1 && xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0) {
+ if (level > 1 &&
+ (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
+ xdl_simplify_non_conflicts(xe1, changes, level > 2) < 0)) {
xdl_cleanup_merge(changes);
return -1;
}