Skip to content

Commit 7bb5321

Browse files
committed
Merge branch 'rs/diff-ihc'
* rs/diff-ihc: diff: add option to show context between close hunks Conflicts: Documentation/diff-options.txt
2 parents ff32340 + 6d0e674 commit 7bb5321

File tree

7 files changed

+106
-1
lines changed

7 files changed

+106
-1
lines changed

Documentation/diff-options.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ endif::git-format-patch[]
205205
differences even if one line has whitespace where the other
206206
line has none.
207207

208+
--inter-hunk-context=<lines>::
209+
Show the context between diff hunks, up to the specified number
210+
of lines, thereby fusing hunks that are close to each other.
211+
208212
--exit-code::
209213
Make the program exit with codes similar to diff(1).
210214
That is, it exits with 1 if there were differences and

contrib/completion/git-completion.bash

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,7 @@ _git_diff ()
776776
--no-ext-diff
777777
--no-prefix --src-prefix= --dst-prefix=
778778
--base --ours --theirs
779+
--inter-hunk-context=
779780
"
780781
return
781782
;;
@@ -967,6 +968,7 @@ _git_log ()
967968
--color-words --walk-reflogs
968969
--parents --children --full-history
969970
--merge
971+
--inter-hunk-context=
970972
"
971973
return
972974
;;

diff.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,7 @@ static void builtin_diff(const char *name_a,
14691469
ecbdata.file = o->file;
14701470
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
14711471
xecfg.ctxlen = o->context;
1472+
xecfg.interhunkctxlen = o->interhunkcontext;
14721473
xecfg.flags = XDL_EMIT_FUNCNAMES;
14731474
if (pe)
14741475
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
@@ -2538,6 +2539,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
25382539
options->b_prefix = arg + 13;
25392540
else if (!strcmp(arg, "--no-prefix"))
25402541
options->a_prefix = options->b_prefix = "";
2542+
else if (opt_arg(arg, '\0', "inter-hunk-context",
2543+
&options->interhunkcontext))
2544+
;
25412545
else if (!prefixcmp(arg, "--output=")) {
25422546
options->file = fopen(arg + strlen("--output="), "w");
25432547
options->close_file = 1;

diff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct diff_options {
7878
const char *a_prefix, *b_prefix;
7979
unsigned flags;
8080
int context;
81+
int interhunkcontext;
8182
int break_opt;
8283
int detect_rename;
8384
int skip_stat_unmatch;

t/t4032-diff-inter-hunk-context.sh

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/bin/sh
2+
3+
test_description='diff hunk fusing'
4+
5+
. ./test-lib.sh
6+
7+
f() {
8+
echo $1
9+
i=1
10+
while test $i -le $2
11+
do
12+
echo $i
13+
i=$(expr $i + 1)
14+
done
15+
echo $3
16+
}
17+
18+
t() {
19+
case $# in
20+
4) hunks=$4; cmd="diff -U$3";;
21+
5) hunks=$5; cmd="diff -U$3 --inter-hunk-context=$4";;
22+
esac
23+
label="$cmd, $1 common $2"
24+
file=f$1
25+
expected=expected.$file.$3.$hunks
26+
27+
if ! test -f $file
28+
then
29+
f A $1 B >$file
30+
git add $file
31+
git commit -q -m. $file
32+
f X $1 Y >$file
33+
fi
34+
35+
test_expect_success "$label: count hunks ($hunks)" "
36+
test $(git $cmd $file | grep '^@@ ' | wc -l) = $hunks
37+
"
38+
39+
test -f $expected &&
40+
test_expect_success "$label: check output" "
41+
git $cmd $file | grep -v '^index ' >actual &&
42+
test_cmp $expected actual
43+
"
44+
}
45+
46+
cat <<EOF >expected.f1.0.1 || exit 1
47+
diff --git a/f1 b/f1
48+
--- a/f1
49+
+++ b/f1
50+
@@ -1,3 +1,3 @@
51+
-A
52+
+X
53+
1
54+
-B
55+
+Y
56+
EOF
57+
58+
cat <<EOF >expected.f1.0.2 || exit 1
59+
diff --git a/f1 b/f1
60+
--- a/f1
61+
+++ b/f1
62+
@@ -1 +1 @@
63+
-A
64+
+X
65+
@@ -3 +3 @@ A
66+
-B
67+
+Y
68+
EOF
69+
70+
# common lines ctx intrctx hunks
71+
t 1 line 0 2
72+
t 1 line 0 0 2
73+
t 1 line 0 1 1
74+
t 1 line 0 2 1
75+
t 1 line 1 1
76+
77+
t 2 lines 0 2
78+
t 2 lines 0 0 2
79+
t 2 lines 0 1 2
80+
t 2 lines 0 2 1
81+
t 2 lines 1 1
82+
83+
t 3 lines 1 2
84+
t 3 lines 1 0 2
85+
t 3 lines 1 1 1
86+
t 3 lines 1 2 1
87+
88+
t 9 lines 3 2
89+
t 9 lines 3 2 2
90+
t 9 lines 3 3 1
91+
92+
test_done

xdiff/xdiff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long
8484

8585
typedef struct s_xdemitconf {
8686
long ctxlen;
87+
long interhunkctxlen;
8788
unsigned long flags;
8889
find_func_t find_func;
8990
void *find_func_priv;

xdiff/xemit.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *
5959
*/
6060
xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
6161
xdchange_t *xch, *xchp;
62+
long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
6263

6364
for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
64-
if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen)
65+
if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common)
6566
break;
6667

6768
return xchp;

0 commit comments

Comments
 (0)