提交 9b55aa03 编写于 作者: J Junio C Hamano

Merge branch 'rs/diff-whole-function'

* rs/diff-whole-function:
  diff: add option to show whole functions as context
  xdiff: factor out get_func_line()
...@@ -408,6 +408,10 @@ endif::git-format-patch[] ...@@ -408,6 +408,10 @@ endif::git-format-patch[]
Show the context between diff hunks, up to the specified number Show the context between diff hunks, up to the specified number
of lines, thereby fusing hunks that are close to each other. of lines, thereby fusing hunks that are close to each other.
-W::
--function-context::
Show whole surrounding functions of changes.
ifndef::git-format-patch[] ifndef::git-format-patch[]
--exit-code:: --exit-code::
Make the program exit with codes similar to diff(1). Make the program exit with codes similar to diff(1).
......
...@@ -2169,6 +2169,8 @@ static void builtin_diff(const char *name_a, ...@@ -2169,6 +2169,8 @@ static void builtin_diff(const char *name_a,
xecfg.ctxlen = o->context; xecfg.ctxlen = o->context;
xecfg.interhunkctxlen = o->interhunkcontext; xecfg.interhunkctxlen = o->interhunkcontext;
xecfg.flags = XDL_EMIT_FUNCNAMES; xecfg.flags = XDL_EMIT_FUNCNAMES;
if (DIFF_OPT_TST(o, FUNCCONTEXT))
xecfg.flags |= XDL_EMIT_FUNCCONTEXT;
if (pe) if (pe)
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags); xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
if (!diffopts) if (!diffopts)
...@@ -3536,6 +3538,12 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) ...@@ -3536,6 +3538,12 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
else if (opt_arg(arg, '\0', "inter-hunk-context", else if (opt_arg(arg, '\0', "inter-hunk-context",
&options->interhunkcontext)) &options->interhunkcontext))
; ;
else if (!strcmp(arg, "-W"))
DIFF_OPT_SET(options, FUNCCONTEXT);
else if (!strcmp(arg, "--function-context"))
DIFF_OPT_SET(options, FUNCCONTEXT);
else if (!strcmp(arg, "--no-function-context"))
DIFF_OPT_CLR(options, FUNCCONTEXT);
else if ((argcount = parse_long_opt("output", av, &optarg))) { else if ((argcount = parse_long_opt("output", av, &optarg))) {
options->file = fopen(optarg, "w"); options->file = fopen(optarg, "w");
if (!options->file) if (!options->file)
......
...@@ -79,6 +79,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) ...@@ -79,6 +79,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
#define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26) #define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26)
#define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27) #define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
#define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28) #define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28)
#define DIFF_OPT_FUNCCONTEXT (1 << 29)
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
......
#!/bin/sh
test_description='diff function context'
. ./test-lib.sh
. "$TEST_DIRECTORY"/diff-lib.sh
cat <<\EOF >hello.c
#include <stdio.h>
static int a(void)
{
/*
* Dummy.
*/
}
static int hello_world(void)
{
/* Classic. */
printf("Hello world.\n");
/* Success! */
return 0;
}
static int b(void)
{
/*
* Dummy, too.
*/
}
int main(int argc, char **argv)
{
a();
b();
return hello_world();
}
EOF
test_expect_success 'setup' '
git add hello.c &&
test_tick &&
git commit -m initial &&
grep -v Classic <hello.c >hello.c.new &&
mv hello.c.new hello.c
'
cat <<\EOF >expected
diff --git a/hello.c b/hello.c
--- a/hello.c
+++ b/hello.c
@@ -10,8 +10,7 @@ static int a(void)
static int hello_world(void)
{
- /* Classic. */
printf("Hello world.\n");
/* Success! */
return 0;
}
EOF
test_expect_success 'diff -U0 -W' '
git diff -U0 -W >actual &&
compare_diff_patch actual expected
'
cat <<\EOF >expected
diff --git a/hello.c b/hello.c
--- a/hello.c
+++ b/hello.c
@@ -9,9 +9,8 @@ static int a(void)
static int hello_world(void)
{
- /* Classic. */
printf("Hello world.\n");
/* Success! */
return 0;
}
EOF
test_expect_success 'diff -W' '
git diff -W >actual &&
compare_diff_patch actual expected
'
test_done
...@@ -43,6 +43,7 @@ extern "C" { ...@@ -43,6 +43,7 @@ extern "C" {
#define XDL_EMIT_FUNCNAMES (1 << 0) #define XDL_EMIT_FUNCNAMES (1 << 0)
#define XDL_EMIT_COMMON (1 << 1) #define XDL_EMIT_COMMON (1 << 1)
#define XDL_EMIT_FUNCCONTEXT (1 << 2)
#define XDL_MMB_READONLY (1 << 0) #define XDL_MMB_READONLY (1 << 0)
......
...@@ -100,14 +100,40 @@ static int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ...@@ -100,14 +100,40 @@ static int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
return 0; return 0;
} }
struct func_line {
long len;
char buf[80];
};
static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg,
struct func_line *func_line, long start, long limit)
{
find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff;
long l, size, step = (start > limit) ? -1 : 1;
char *buf, dummy[1];
buf = func_line ? func_line->buf : dummy;
size = func_line ? sizeof(func_line->buf) : sizeof(dummy);
for (l = start; l != limit && 0 <= l && l < xe->xdf1.nrec; l += step) {
const char *rec;
long reclen = xdl_get_rec(&xe->xdf1, l, &rec);
long len = ff(rec, reclen, buf, size, xecfg->find_func_priv);
if (len >= 0) {
if (func_line)
func_line->len = len;
return l;
}
}
return -1;
}
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg) { xdemitconf_t const *xecfg) {
long s1, s2, e1, e2, lctx; long s1, s2, e1, e2, lctx;
xdchange_t *xch, *xche; xdchange_t *xch, *xche;
char funcbuf[80];
long funclen = 0;
long funclineprev = -1; long funclineprev = -1;
find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff; struct func_line func_line = { 0 };
if (xecfg->flags & XDL_EMIT_COMMON) if (xecfg->flags & XDL_EMIT_COMMON)
return xdl_emit_common(xe, xscr, ecb, xecfg); return xdl_emit_common(xe, xscr, ecb, xecfg);
...@@ -118,6 +144,17 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ...@@ -118,6 +144,17 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) {
long fs1 = get_func_line(xe, xecfg, NULL, xch->i1, -1);
if (fs1 < 0)
fs1 = 0;
if (fs1 < s1) {
s2 -= s1 - fs1;
s1 = fs1;
}
}
again:
lctx = xecfg->ctxlen; lctx = xecfg->ctxlen;
lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1)); lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1));
lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2)); lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2));
...@@ -125,27 +162,43 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ...@@ -125,27 +162,43 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
e1 = xche->i1 + xche->chg1 + lctx; e1 = xche->i1 + xche->chg1 + lctx;
e2 = xche->i2 + xche->chg2 + lctx; e2 = xche->i2 + xche->chg2 + lctx;
if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) {
long fe1 = get_func_line(xe, xecfg, NULL,
xche->i1 + xche->chg1,
xe->xdf1.nrec);
if (fe1 < 0)
fe1 = xe->xdf1.nrec;
if (fe1 > e1) {
e2 += fe1 - e1;
e1 = fe1;
}
/*
* Overlap with next change? Then include it
* in the current hunk and start over to find
* its new end.
*/
if (xche->next) {
long l = xche->next->i1;
if (l <= e1 ||
get_func_line(xe, xecfg, NULL, l, e1) < 0) {
xche = xche->next;
goto again;
}
}
}
/* /*
* Emit current hunk header. * Emit current hunk header.
*/ */
if (xecfg->flags & XDL_EMIT_FUNCNAMES) { if (xecfg->flags & XDL_EMIT_FUNCNAMES) {
long l; get_func_line(xe, xecfg, &func_line,
for (l = s1 - 1; l >= 0 && l > funclineprev; l--) { s1 - 1, funclineprev);
const char *rec;
long reclen = xdl_get_rec(&xe->xdf1, l, &rec);
long newfunclen = ff(rec, reclen, funcbuf,
sizeof(funcbuf),
xecfg->find_func_priv);
if (newfunclen >= 0) {
funclen = newfunclen;
break;
}
}
funclineprev = s1 - 1; funclineprev = s1 - 1;
} }
if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
funcbuf, funclen, ecb) < 0) func_line.buf, func_line.len, ecb) < 0)
return -1; return -1;
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册