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,