X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=xdiff-interface.c;h=e8ef46d10dc53a1ee1781d07685984734bc3160f;hb=6e13921b4f7adcc7316a76c0c4955b85b1589a65;hp=944ad9887f5c94ca0e63f9a6c901447634f871ce;hpb=15dc66abf02fa22a03d709725bcaeeec4b809834;p=git.git diff --git a/xdiff-interface.c b/xdiff-interface.c index 944ad9887..e8ef46d10 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -1,6 +1,9 @@ #include "cache.h" #include "xdiff-interface.h" -#include "strbuf.h" +#include "xdiff/xtypes.h" +#include "xdiff/xdiffi.h" +#include "xdiff/xemit.h" +#include "xdiff/xmacros.h" struct xdiff_emit_state { xdiff_emit_consume_fn consume; @@ -153,6 +156,50 @@ int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2, return ret; } +struct xdiff_emit_hunk_state { + xdiff_emit_hunk_consume_fn consume; + void *consume_callback_data; +}; + +static int process_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, + xdemitconf_t const *xecfg) +{ + long s1, s2, same, p_next, t_next; + xdchange_t *xch, *xche; + struct xdiff_emit_hunk_state *state = ecb->priv; + xdiff_emit_hunk_consume_fn fn = state->consume; + void *consume_callback_data = state->consume_callback_data; + + for (xch = xscr; xch; xch = xche->next) { + xche = xdl_get_hunk(xch, xecfg); + + s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); + s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); + same = s2 + XDL_MAX(xch->i1 - s1, 0); + p_next = xche->i1 + xche->chg1; + t_next = xche->i2 + xche->chg2; + + fn(consume_callback_data, same, p_next, t_next); + } + return 0; +} + +int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2, + xdiff_emit_hunk_consume_fn fn, void *consume_callback_data, + xpparam_t const *xpp, xdemitconf_t *xecfg) +{ + struct xdiff_emit_hunk_state state; + xdemitcb_t ecb; + + memset(&state, 0, sizeof(state)); + memset(&ecb, 0, sizeof(ecb)); + state.consume = fn; + state.consume_callback_data = consume_callback_data; + xecfg->emit_func = (void (*)())process_diff; + ecb.priv = &state; + return xdi_diff(mf1, mf2, xpp, xecfg, &ecb); +} + int read_mmfile(mmfile_t *ptr, const char *filename) { struct stat st; @@ -191,34 +238,57 @@ struct ff_regs { static long ff_regexp(const char *line, long len, char *buffer, long buffer_size, void *priv) { - char *line_buffer = xstrndup(line, len); /* make NUL terminated */ + char *line_buffer; struct ff_regs *regs = priv; regmatch_t pmatch[2]; - int result = 0, i; + int i; + int result = -1; + + /* Exclude terminating newline (and cr) from matching */ + if (len > 0 && line[len-1] == '\n') { + if (len > 1 && line[len-2] == '\r') + len -= 2; + else + len--; + } + + line_buffer = xstrndup(line, len); /* make NUL terminated */ + + /* Exclude terminating newline (and cr) from matching */ + if (len > 0 && line[len-1] == '\n') { + if (len > 1 && line[len-2] == '\r') + len -= 2; + else + len--; + } + + line_buffer = xstrndup(line, len); /* make NUL terminated */ for (i = 0; i < regs->nr; i++) { struct ff_reg *reg = regs->array + i; - if (reg->negate ^ !!regexec(®->re, - line_buffer, 2, pmatch, 0)) { - free(line_buffer); - return -1; + if (!regexec(®->re, line_buffer, 2, pmatch, 0)) { + if (reg->negate) + goto fail; + break; } } + if (regs->nr <= i) + goto fail; i = pmatch[1].rm_so >= 0 ? 1 : 0; line += pmatch[i].rm_so; result = pmatch[i].rm_eo - pmatch[i].rm_so; if (result > buffer_size) result = buffer_size; else - while (result > 0 && (isspace(line[result - 1]) || - line[result - 1] == '\n')) + while (result > 0 && (isspace(line[result - 1]))) result--; memcpy(buffer, line, result); + fail: free(line_buffer); return result; } -void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) +void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value, int cflags) { int i; struct ff_regs *regs; @@ -243,9 +313,29 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) expression = buffer = xstrndup(value, ep - value); else expression = value; - if (regcomp(®->re, expression, 0)) + if (regcomp(®->re, expression, cflags)) die("Invalid regexp to look for hunk header: %s", expression); free(buffer); value = ep + 1; } } + +int git_xmerge_style = -1; + +int git_xmerge_config(const char *var, const char *value, void *cb) +{ + if (!strcasecmp(var, "merge.conflictstyle")) { + if (!value) + die("'%s' is not a boolean", var); + if (!strcmp(value, "diff3")) + git_xmerge_style = XDL_MERGE_DIFF3; + else if (!strcmp(value, "merge")) + git_xmerge_style = 0; + else + die("unknown style '%s' given for '%s'", + value, var); + return 0; + } + return git_default_config(var, value, cb); +} +