# HG changeset patch # User Jun Wu # Date 2018-03-03 20:38:41 # Node ID b3c9c483cac9f4e5aabebd2d4ad0c61c872ecb72 # Parent 9e7b14caf67f898e8f5364af04d4cb28b7259a86 xdiff: add a bdiff hunk mode xdiff generated hunks for the differences (ex. questionmarks in the `@@ -?,? +?,? @@` part from `diff --git` output). However, bdiff generates matched hunks instead. This patch adds a `XDL_EMIT_BDIFFHUNK` flag used by the output function `xdl_call_hunk_func`. Once set, xdiff will generate bdiff-like hunks instead. That makes it easier to use xdiff as a drop-in replacement of bdiff. Note that since `bdiff('', '')` returns `[(0, 0, 0, 0)]`, the shortcut path `if (xscr)` is removed. I have checked functions called with `xscr` argument (`xdl_mark_ignorable`, `xdl_call_hunk_func`, `xdl_emit_diff`, `xdl_free_script`) work just fine with `xscr = NULL`. Test Plan: Will be tested in a later patch. Differential Revision: https://phab.mercurial-scm.org/D2575 diff --git a/mercurial/thirdparty/xdiff/xdiff.h b/mercurial/thirdparty/xdiff/xdiff.h --- a/mercurial/thirdparty/xdiff/xdiff.h +++ b/mercurial/thirdparty/xdiff/xdiff.h @@ -48,6 +48,9 @@ extern "C" { /* xdemitconf_t.flags */ #define XDL_EMIT_FUNCNAMES (1 << 0) #define XDL_EMIT_FUNCCONTEXT (1 << 2) +/* emit bdiff-style "matched" (a1, a2, b1, b2) hunks instead of "different" + * (a1, a2 - a1, b1, b2 - b1) hunks */ +#define XDL_EMIT_BDIFFHUNK (1 << 4) #define XDL_MMB_READONLY (1 << 0) diff --git a/mercurial/thirdparty/xdiff/xdiffi.c b/mercurial/thirdparty/xdiff/xdiffi.c --- a/mercurial/thirdparty/xdiff/xdiffi.c +++ b/mercurial/thirdparty/xdiff/xdiffi.c @@ -975,15 +975,32 @@ static int xdl_call_hunk_func(xdfenv_t * xdemitconf_t const *xecfg) { xdchange_t *xch, *xche; - - for (xch = xscr; xch; xch = xche->next) { - xche = xdl_get_hunk(&xch, xecfg); - if (!xch) - break; - if (xecfg->hunk_func(xch->i1, xche->i1 + xche->chg1 - xch->i1, - xch->i2, xche->i2 + xche->chg2 - xch->i2, - ecb->priv) < 0) + if ((xecfg->flags & XDL_EMIT_BDIFFHUNK) != 0) { + long i1 = 0, i2 = 0, n1 = xe->xdf1.nrec, n2 = xe->xdf2.nrec; + for (xch = xscr; xch; xch = xche->next) { + xche = xdl_get_hunk(&xch, xecfg); + if (!xch) + break; + if (xch->i1 > i1 || xch->i2 > i2) { + if (xecfg->hunk_func(i1, xch->i1, i2, xch->i2, ecb->priv) < 0) + return -1; + } + i1 = xche->i1 + xche->chg1; + i2 = xche->i2 + xche->chg2; + } + if (xecfg->hunk_func(i1, n1, i2, n2, ecb->priv) < 0) return -1; + } else { + for (xch = xscr; xch; xch = xche->next) { + xche = xdl_get_hunk(&xch, xecfg); + if (!xch) + break; + if (xecfg->hunk_func( + xch->i1, xche->i1 + xche->chg1 - xch->i1, + xch->i2, xche->i2 + xche->chg2 - xch->i2, + ecb->priv) < 0) + return -1; + } } return 0; } @@ -1026,18 +1043,15 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf xdl_free_env(&xe); return -1; } - if (xscr) { - if (xpp->flags & XDF_IGNORE_BLANK_LINES) - xdl_mark_ignorable(xscr, &xe, xpp->flags); - if (ef(&xe, xscr, ecb, xecfg) < 0) { - - xdl_free_script(xscr); - xdl_free_env(&xe); - return -1; - } + if (xpp->flags & XDF_IGNORE_BLANK_LINES) + xdl_mark_ignorable(xscr, &xe, xpp->flags); + if (ef(&xe, xscr, ecb, xecfg) < 0) { xdl_free_script(xscr); + xdl_free_env(&xe); + return -1; } + xdl_free_script(xscr); xdl_free_env(&xe); return 0;