vendor/libgit2/src/xdiff/xmerge.c in rugged-1.3.2.3 vs vendor/libgit2/src/xdiff/xmerge.c in rugged-1.4.2
- old
+ new
@@ -86,11 +86,11 @@
/* were there conflicts? */
for (; c; c = next_c) {
if (c->mode == 0)
count++;
next_c = c->next;
- free(c);
+ xdl_free(c);
}
return count;
}
static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
@@ -107,57 +107,48 @@
return -1;
}
return 0;
}
-static int xdl_recs_copy_0(size_t *out, int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
{
xrecord_t **recs;
- size_t size = 0;
+ int size = 0;
- *out = 0;
-
recs = (use_orig ? xe->xdf1.recs : xe->xdf2.recs) + i;
if (count < 1)
return 0;
- for (i = 0; i < count; ) {
+ for (i = 0; i < count; size += recs[i++]->size)
if (dest)
memcpy(dest + size, recs[i]->ptr, recs[i]->size);
-
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, recs[i++]->size);
- }
-
if (add_nl) {
i = recs[count - 1]->size;
if (i == 0 || recs[count - 1]->ptr[i - 1] != '\n') {
if (needs_cr) {
if (dest)
dest[size] = '\r';
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, 1);
+ size++;
}
if (dest)
dest[size] = '\n';
-
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, 1);
+ size++;
}
}
-
- *out = size;
- return 0;
+ return size;
}
-static int xdl_recs_copy(size_t *out, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
{
- return xdl_recs_copy_0(out, 0, xe, i, count, needs_cr, add_nl, dest);
+ return xdl_recs_copy_0(0, xe, i, count, needs_cr, add_nl, dest);
}
-static int xdl_orig_copy(size_t *out, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+static int xdl_orig_copy(xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
{
- return xdl_recs_copy_0(out, 1, xe, i, count, needs_cr, add_nl, dest);
+ return xdl_recs_copy_0(1, xe, i, count, needs_cr, add_nl, dest);
}
/*
* Returns 1 if the i'th line ends in CR/LF (if it is the last line and
* has no eol, the preceding line, if any), 0 if it ends in LF-only, and
@@ -200,36 +191,30 @@
needs_cr = is_eol_crlf(&xe1->xdf1, 0);
/* If still undecided, use LF-only */
return needs_cr < 0 ? 0 : needs_cr;
}
-static int fill_conflict_hunk(size_t *out, xdfenv_t *xe1, const char *name1,
+static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
xdfenv_t *xe2, const char *name2,
const char *name3,
- size_t size, int i, int style,
+ int size, int i, int style,
xdmerge_t *m, char *dest, int marker_size)
{
- int marker1_size = (name1 ? (int)strlen(name1) + 1 : 0);
- int marker2_size = (name2 ? (int)strlen(name2) + 1 : 0);
- int marker3_size = (name3 ? (int)strlen(name3) + 1 : 0);
+ int marker1_size = (name1 ? strlen(name1) + 1 : 0);
+ int marker2_size = (name2 ? strlen(name2) + 1 : 0);
+ int marker3_size = (name3 ? strlen(name3) + 1 : 0);
int needs_cr = is_cr_needed(xe1, xe2, m);
- size_t copied;
- *out = 0;
-
if (marker_size <= 0)
marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
/* Before conflicting part */
- if (xdl_recs_copy(&copied, xe1, i, m->i1 - i, 0, 0,
- dest ? dest + size : NULL) < 0)
- return -1;
+ size += xdl_recs_copy(xe1, i, m->i1 - i, 0, 0,
+ dest ? dest + size : NULL);
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-
if (!dest) {
- GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker1_size);
+ size += marker_size + 1 + needs_cr + marker1_size;
} else {
memset(dest + size, '<', marker_size);
size += marker_size;
if (marker1_size) {
dest[size] = ' ';
@@ -240,20 +225,17 @@
dest[size++] = '\r';
dest[size++] = '\n';
}
/* Postimage from side #1 */
- if (xdl_recs_copy(&copied, xe1, m->i1, m->chg1, needs_cr, 1,
- dest ? dest + size : NULL) < 0)
- return -1;
+ size += xdl_recs_copy(xe1, m->i1, m->chg1, needs_cr, 1,
+ dest ? dest + size : NULL);
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-
- if (style == XDL_MERGE_DIFF3) {
+ if (style == XDL_MERGE_DIFF3 || style == XDL_MERGE_ZEALOUS_DIFF3) {
/* Shared preimage */
if (!dest) {
- GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker3_size);
+ size += marker_size + 1 + needs_cr + marker3_size;
} else {
memset(dest + size, '|', marker_size);
size += marker_size;
if (marker3_size) {
dest[size] = ' ';
@@ -262,36 +244,29 @@
}
if (needs_cr)
dest[size++] = '\r';
dest[size++] = '\n';
}
-
- if (xdl_orig_copy(&copied, xe1, m->i0, m->chg0, needs_cr, 1,
- dest ? dest + size : NULL) < 0)
- return -1;
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
+ size += xdl_orig_copy(xe1, m->i0, m->chg0, needs_cr, 1,
+ dest ? dest + size : NULL);
}
if (!dest) {
- GIT_ERROR_CHECK_ALLOC_ADD4(&size, size, marker_size, 1, needs_cr);
+ size += marker_size + 1 + needs_cr;
} else {
memset(dest + size, '=', marker_size);
size += marker_size;
if (needs_cr)
dest[size++] = '\r';
dest[size++] = '\n';
}
/* Postimage from side #2 */
-
- if (xdl_recs_copy(&copied, xe2, m->i2, m->chg2, needs_cr, 1,
- dest ? dest + size : NULL) < 0)
- return -1;
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-
+ size += xdl_recs_copy(xe2, m->i2, m->chg2, needs_cr, 1,
+ dest ? dest + size : NULL);
if (!dest) {
- GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker2_size);
+ size += marker_size + 1 + needs_cr + marker2_size;
} else {
memset(dest + size, '>', marker_size);
size += marker_size;
if (marker2_size) {
dest[size] = ' ';
@@ -300,75 +275,87 @@
}
if (needs_cr)
dest[size++] = '\r';
dest[size++] = '\n';
}
-
- *out = size;
- return 0;
+ return size;
}
-static int xdl_fill_merge_buffer(size_t *out,
- xdfenv_t *xe1, const char *name1,
+static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
xdfenv_t *xe2, const char *name2,
const char *ancestor_name,
int favor,
xdmerge_t *m, char *dest, int style,
int marker_size)
{
- size_t size, copied;
- int i;
+ int size, i;
- *out = 0;
-
for (size = i = 0; m; m = m->next) {
if (favor && !m->mode)
m->mode = favor;
- if (m->mode == 0) {
- if (fill_conflict_hunk(&size, xe1, name1, xe2, name2,
+ if (m->mode == 0)
+ size = fill_conflict_hunk(xe1, name1, xe2, name2,
ancestor_name,
size, i, style, m, dest,
- marker_size) < 0)
- return -1;
- }
+ marker_size);
else if (m->mode & 3) {
/* Before conflicting part */
- if (xdl_recs_copy(&copied, xe1, i, m->i1 - i, 0, 0,
- dest ? dest + size : NULL) < 0)
- return -1;
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
-
+ size += xdl_recs_copy(xe1, i, m->i1 - i, 0, 0,
+ dest ? dest + size : NULL);
/* Postimage from side #1 */
if (m->mode & 1) {
int needs_cr = is_cr_needed(xe1, xe2, m);
- if (xdl_recs_copy(&copied, xe1, m->i1, m->chg1, needs_cr, (m->mode & 2),
- dest ? dest + size : NULL) < 0)
- return -1;
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
+ size += xdl_recs_copy(xe1, m->i1, m->chg1, needs_cr, (m->mode & 2),
+ dest ? dest + size : NULL);
}
-
/* Postimage from side #2 */
- if (m->mode & 2) {
- if (xdl_recs_copy(&copied, xe2, m->i2, m->chg2, 0, 0,
- dest ? dest + size : NULL) < 0)
- return -1;
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
- }
+ if (m->mode & 2)
+ size += xdl_recs_copy(xe2, m->i2, m->chg2, 0, 0,
+ dest ? dest + size : NULL);
} else
continue;
i = m->i1 + m->chg1;
}
+ size += xdl_recs_copy(xe1, i, xe1->xdf2.nrec - i, 0, 0,
+ dest ? dest + size : NULL);
+ return size;
+}
- if (xdl_recs_copy(&copied, xe1, i, xe1->xdf2.nrec - i, 0, 0,
- dest ? dest + size : NULL) < 0)
- return -1;
- GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
+static int recmatch(xrecord_t *rec1, xrecord_t *rec2, unsigned long flags)
+{
+ return xdl_recmatch(rec1->ptr, rec1->size,
+ rec2->ptr, rec2->size, flags);
+}
- *out = size;
- return 0;
+/*
+ * Remove any common lines from the beginning and end of the conflicted region.
+ */
+static void xdl_refine_zdiff3_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
+ xpparam_t const *xpp)
+{
+ xrecord_t **rec1 = xe1->xdf2.recs, **rec2 = xe2->xdf2.recs;
+ for (; m; m = m->next) {
+ /* let's handle just the conflicts */
+ if (m->mode)
+ continue;
+
+ while(m->chg1 && m->chg2 &&
+ recmatch(rec1[m->i1], rec2[m->i2], xpp->flags)) {
+ m->chg1--;
+ m->chg2--;
+ m->i1++;
+ m->i2++;
+ }
+ while (m->chg1 && m->chg2 &&
+ recmatch(rec1[m->i1 + m->chg1 - 1],
+ rec2[m->i2 + m->chg2 - 1], xpp->flags)) {
+ m->chg1--;
+ m->chg2--;
+ }
+ }
}
/*
* Sometimes, changes are not quite identical, but differ in only a few
* lines. Try hard to show only these few lines as conflicting.
@@ -467,11 +454,11 @@
{
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);
+ xdl_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 --
@@ -527,11 +514,26 @@
int i0, i1, i2, chg0, chg1, chg2;
int level = xmp->level;
int style = xmp->style;
int favor = xmp->favor;
- if (style == XDL_MERGE_DIFF3) {
+ /*
+ * XDL_MERGE_DIFF3 does not attempt to refine conflicts by looking
+ * at common areas of sides 1 & 2, because the base (side 0) does
+ * not match and is being shown. Similarly, simplification of
+ * non-conflicts is also skipped due to the skipping of conflict
+ * refinement.
+ *
+ * XDL_MERGE_ZEALOUS_DIFF3, on the other hand, will attempt to
+ * refine conflicts looking for common areas of sides 1 & 2.
+ * However, since the base is being shown and does not match,
+ * it will only look for common areas at the beginning or end
+ * of the conflict block. Since XDL_MERGE_ZEALOUS_DIFF3's
+ * conflict refinement is much more limited in this fashion, the
+ * conflict simplification will be skipped.
+ */
+ if (style == XDL_MERGE_DIFF3 || style == XDL_MERGE_ZEALOUS_DIFF3) {
/*
* "diff3 -m" output does not make sense for anything
* more aggressive than XDL_MERGE_EAGER.
*/
if (XDL_MERGE_EAGER < level)
@@ -648,38 +650,35 @@
xscr2 = xscr2->next;
}
if (!changes)
changes = c;
/* refine conflicts */
- if (XDL_MERGE_ZEALOUS <= level &&
- (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
- xdl_simplify_non_conflicts(xe1, changes,
- XDL_MERGE_ZEALOUS < level) < 0)) {
+ if (style == XDL_MERGE_ZEALOUS_DIFF3) {
+ xdl_refine_zdiff3_conflicts(xe1, xe2, changes, xpp);
+ } else if (XDL_MERGE_ZEALOUS <= level &&
+ (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
+ xdl_simplify_non_conflicts(xe1, changes,
+ XDL_MERGE_ZEALOUS < level) < 0)) {
xdl_cleanup_merge(changes);
return -1;
}
/* output */
if (result) {
int marker_size = xmp->marker_size;
- size_t size;
-
- if (xdl_fill_merge_buffer(&size, xe1, name1, xe2, name2,
+ int size = xdl_fill_merge_buffer(xe1, name1, xe2, name2,
ancestor_name,
favor, changes, NULL, style,
- marker_size) < 0)
- return -1;
-
+ marker_size);
result->ptr = xdl_malloc(size);
if (!result->ptr) {
xdl_cleanup_merge(changes);
return -1;
}
result->size = size;
- if (xdl_fill_merge_buffer(&size, xe1, name1, xe2, name2,
+ xdl_fill_merge_buffer(xe1, name1, xe2, name2,
ancestor_name, favor, changes,
- result->ptr, style, marker_size) < 0)
- return -1;
+ result->ptr, style, marker_size);
}
return xdl_cleanup_merge(changes);
}
int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
@@ -715,25 +714,13 @@
return -1;
}
status = 0;
if (!xscr1) {
result->ptr = xdl_malloc(mf2->size);
- if (!result->ptr) {
- xdl_free_script(xscr2);
- xdl_free_env(&xe1);
- xdl_free_env(&xe2);
- return -1;
- }
memcpy(result->ptr, mf2->ptr, mf2->size);
result->size = mf2->size;
} else if (!xscr2) {
result->ptr = xdl_malloc(mf1->size);
- if (!result->ptr) {
- xdl_free_script(xscr1);
- xdl_free_env(&xe1);
- xdl_free_env(&xe2);
- return -1;
- }
memcpy(result->ptr, mf1->ptr, mf1->size);
result->size = mf1->size;
} else {
status = xdl_do_merge(&xe1, xscr1,
&xe2, xscr2,