@matheusbsbs / matheus-bagliano / commits / ee95ec5d58
Fork 0

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>

Johannes Schindelin committed Feb 17, 2008 at 19:07 UTC ee95ec5d58d536243966de6ee810d345074b755e
4 files changed +39 -5
builtin-merge-file.c
+1 -1
@@ -46,7 +46,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
46 }
47
48 ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
49 - &xpp, XDL_MERGE_ZEALOUS, &result);
49 + &xpp, XDL_MERGE_ZEALOUS_ALNUM, &result);
50
51 for (i = 0; i < 3; i++)
52 free(mmfs[i].ptr);
t/t6023-merge-file.sh
+10
@@ -149,4 +149,14 @@ test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
149
150 '
151
152 +sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit;/" < new6.txt > new8.txt
153 +sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit --/" < new7.txt > new9.txt
154 +
155 +test_expect_success 'ZEALOUS_ALNUM' '
156 +
157 + ! git merge-file -p new8.txt new5.txt new9.txt > merge.out &&
158 + test 1 = $(grep ======= < merge.out | wc -l)
159 +
160 +'
161 +
162 test_done
xdiff/xdiff.h
+1
@@ -53,6 +53,7 @@ extern "C" {
53 #define XDL_MERGE_MINIMAL 0
54 #define XDL_MERGE_EAGER 1
55 #define XDL_MERGE_ZEALOUS 2
56 +#define XDL_MERGE_ZEALOUS_ALNUM 3
57
58 typedef struct s_mmfile {
59 char *ptr;
xdiff/xmerge.c
+27 -4
@@ -248,6 +248,23 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
248 return 0;
249 }
250
251 +static int line_contains_alnum(const char *ptr, long size)
252 +{
253 + while (size--)
254 + if (isalnum(*(ptr++)))
255 + return 1;
256 + return 0;
257 +}
258 +
259 +static int lines_contain_alnum(xdfenv_t *xe, int i, int chg)
260 +{
261 + for (; chg; chg--, i++)
262 + if (line_contains_alnum(xe->xdf2.recs[i]->ptr,
263 + xe->xdf2.recs[i]->size))
264 + return 1;
265 + return 0;
266 +}
267 +
268 /*
269 * This function merges m and m->next, marking everything between those hunks
270 * as conflicting, too.
@@ -266,7 +283,8 @@ static void xdl_merge_two_conflicts(xdmerge_t *m)
283 * it appears simpler -- because it takes up less (or as many) lines --
284 * if the lines are moved into the conflicts.
285 */
269 -static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m)
286 +static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
287 + int simplify_if_no_alnum)
288 {
289 int result = 0;
290
@@ -282,9 +300,12 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m)
300 begin = m->i1 + m->chg1;
301 end = next_m->i1;
302
285 - if (m->mode != 0 || next_m->mode != 0 || end - begin > 3)
303 + if (m->mode != 0 || next_m->mode != 0 ||
304 + (end - begin > 3 &&
305 + (!simplify_if_no_alnum ||
306 + lines_contain_alnum(xe1, begin, end - begin)))) {
307 m = next_m;
287 - else {
308 + } else {
309 result++;
310 xdl_merge_two_conflicts(m);
311 }
@@ -295,6 +316,8 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m)
316 * level == 0: mark all overlapping changes as conflict
317 * level == 1: mark overlapping changes as conflict only if not identical
318 * level == 2: analyze non-identical changes for minimal conflict set
319 + * level == 3: analyze non-identical changes for minimal conflict set, but
320 + * treat hunks not containing any letter or number as conflicting
321 *
322 * returns < 0 on error, == 0 for no conflicts, else number of conflicts
323 */
@@ -400,7 +423,7 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
423 /* refine conflicts */
424 if (level > 1 &&
425 (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
403 - xdl_simplify_non_conflicts(xe1, changes) < 0)) {
426 + xdl_simplify_non_conflicts(xe1, changes, level > 2) < 0)) {
427 xdl_cleanup_merge(changes);
428 return -1;
429 }