Basic function context header This implements a basic callback to extract function context for a diff. It always uses the same search heuristic right now with no regular expressions or language-specific variants. Those will come next, I think.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
diff --git a/src/diff_output.c b/src/diff_output.c
index 8dd110c..bcd39f0 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -196,26 +196,77 @@ static int diff_delta_is_binary_by_size(
return 0;
}
-static void setup_xdiff_options(
- const git_diff_options *opts, xdemitconf_t *cfg, xpparam_t *param)
+static long diff_context_find(
+ const char *line,
+ long line_len,
+ char *out,
+ long out_size,
+ void *payload)
+{
+ diff_context *ctxt = payload;
+ const char *scan;
+ bool found_paren = false;
+
+ if (line_len > 0 && line[line_len - 1] == '\n')
+ line_len--;
+ if (line_len > 0 && line[line_len - 1] == '\r')
+ line_len--;
+ if (!line_len)
+ return -1;
+
+ if (!isalpha(*line))
+ return -1;
+
+ for (scan = &line[line_len - 1]; scan > line && *scan != '('; --scan)
+ /* search backward for ( */;
+ if (scan != line) {
+ found_paren = true;
+ line_len = scan - line;
+
+ for (--scan; scan > line && !isalpha(*scan); --scan)
+ --line_len;
+ }
+
+ if (!line_len)
+ return -1;
+
+ if (out_size > line_len) {
+ memcpy(out, line, line_len);
+
+ if (found_paren)
+ out[line_len++] = '(';
+ out[line_len] = '\0';
+ } else {
+ memcpy(out, line, out_size);
+ line_len = out_size;
+ }
+
+ return line_len;
+}
+
+static void setup_xdiff_options(diff_context *ctxt)
{
- memset(cfg, 0, sizeof(xdemitconf_t));
- memset(param, 0, sizeof(xpparam_t));
+ memset(&ctxt->xdiff_config, 0, sizeof(ctxt->xdiff_config));
+ memset(&ctxt->xdiff_params, 0, sizeof(ctxt->xdiff_params));
+
+ ctxt->xdiff_config.ctxlen =
+ (!ctxt->opts) ? 3 : ctxt->opts->context_lines;
+ ctxt->xdiff_config.interhunkctxlen =
+ (!ctxt->opts) ? 0 : ctxt->opts->interhunk_lines;
- cfg->ctxlen =
- (!opts) ? 3 : opts->context_lines;
- cfg->interhunkctxlen =
- (!opts) ? 0 : opts->interhunk_lines;
+ ctxt->xdiff_config.flags = XDL_EMIT_FUNCNAMES;
+ ctxt->xdiff_config.find_func = diff_context_find;
+ ctxt->xdiff_config.find_func_priv = ctxt;
- if (!opts)
+ if (!ctxt->opts)
return;
- if (opts->flags & GIT_DIFF_IGNORE_WHITESPACE)
- param->flags |= XDF_WHITESPACE_FLAGS;
- if (opts->flags & GIT_DIFF_IGNORE_WHITESPACE_CHANGE)
- param->flags |= XDF_IGNORE_WHITESPACE_CHANGE;
- if (opts->flags & GIT_DIFF_IGNORE_WHITESPACE_EOL)
- param->flags |= XDF_IGNORE_WHITESPACE_AT_EOL;
+ if (ctxt->opts->flags & GIT_DIFF_IGNORE_WHITESPACE)
+ ctxt->xdiff_params.flags |= XDF_WHITESPACE_FLAGS;
+ if (ctxt->opts->flags & GIT_DIFF_IGNORE_WHITESPACE_CHANGE)
+ ctxt->xdiff_params.flags |= XDF_IGNORE_WHITESPACE_CHANGE;
+ if (ctxt->opts->flags & GIT_DIFF_IGNORE_WHITESPACE_EOL)
+ ctxt->xdiff_params.flags |= XDF_IGNORE_WHITESPACE_AT_EOL;
}
@@ -499,7 +550,7 @@ static int diff_context_init(
ctxt->payload = payload;
ctxt->error = 0;
- setup_xdiff_options(ctxt->opts, &ctxt->xdiff_config, &ctxt->xdiff_params);
+ setup_xdiff_options(ctxt);
return 0;
}