Skip to content

Commit 6d0e674

Browse files
René Scharfegitster
authored andcommitted
diff: add option to show context between close hunks
Merge two hunks if there is only the specified number of otherwise unshown context between them. For --inter-hunk-context=1, the resulting patch has the same number of lines but shows uninterrupted context instead of a context header line in between. Patches generated with this option are easier to read but are also more likely to conflict if the file to be patched contains other changes. This patch keeps the default for this option at 0. It is intended to just make the feature available in order to see its advantages and downsides. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 159c88e commit 6d0e674

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
@@ -215,6 +215,10 @@ endif::git-format-patch[]
215215
-w::
216216
Shorthand for "--ignore-all-space".
217217

218+
--inter-hunk-context=<lines>::
219+
Show the context between diff hunks, up to the specified number
220+
of lines, thereby fusing hunks that are close to each other.
221+
218222
--exit-code::
219223
Make the program exit with codes similar to diff(1).
220224
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)