Merge branch 'js/merge'
* js/merge: xdl_merge(): introduce XDL_MERGE_ZEALOUS_ALNUM xdl_merge(): make XDL_MERGE_ZEALOUS output simpler
This commit is contained in:
commit
cb99be7c7d
@ -46,7 +46,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
|
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++)
|
for (i = 0; i < 3; i++)
|
||||||
free(mmfs[i].ptr);
|
free(mmfs[i].ptr);
|
||||||
|
@ -139,4 +139,24 @@ test_expect_success 'binary files cannot be merged' '
|
|||||||
grep "Cannot merge binary files" merge.err
|
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
|
test_done
|
||||||
|
@ -53,6 +53,7 @@ extern "C" {
|
|||||||
#define XDL_MERGE_MINIMAL 0
|
#define XDL_MERGE_MINIMAL 0
|
||||||
#define XDL_MERGE_EAGER 1
|
#define XDL_MERGE_EAGER 1
|
||||||
#define XDL_MERGE_ZEALOUS 2
|
#define XDL_MERGE_ZEALOUS 2
|
||||||
|
#define XDL_MERGE_ZEALOUS_ALNUM 3
|
||||||
|
|
||||||
typedef struct s_mmfile {
|
typedef struct s_mmfile {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
@ -248,10 +248,76 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
|
|||||||
return 0;
|
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 == 0: mark all overlapping changes as conflict
|
||||||
* level == 1: mark overlapping changes as conflict only if not identical
|
* level == 1: mark overlapping changes as conflict only if not identical
|
||||||
* level == 2: analyze non-identical changes for minimal conflict set
|
* 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
|
* returns < 0 on error, == 0 for no conflicts, else number of conflicts
|
||||||
*/
|
*/
|
||||||
@ -355,7 +421,9 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
|
|||||||
if (!changes)
|
if (!changes)
|
||||||
changes = c;
|
changes = c;
|
||||||
/* refine conflicts */
|
/* 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);
|
xdl_cleanup_merge(changes);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user