Merge branch 'rs/diff-ihc'
authorJunio C Hamano <gitster@pobox.com>
Wed, 7 Jan 2009 08:10:14 +0000 (00:10 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 7 Jan 2009 08:10:14 +0000 (00:10 -0800)
* rs/diff-ihc:
diff: add option to show context between close hunks

Conflicts:
Documentation/diff-options.txt

Documentation/diff-options.txt
contrib/completion/git-completion.bash
diff.c
diff.h
t/t4032-diff-inter-hunk-context.sh [new file with mode: 0755]
xdiff/xdiff.h
xdiff/xemit.c
index b432d2518aba3d1be9d86fb1613bbe2f5fa9da4d..671f533ca30c1fb0ddae8a15f9c586c431c8fef5 100644 (file)
@@ -205,6 +205,10 @@ endif::git-format-patch[]
        differences even if one line has whitespace where the other
        line has none.
 
+--inter-hunk-context=<lines>::
+       Show the context between diff hunks, up to the specified number
+       of lines, thereby fusing hunks that are close to each other.
+
 --exit-code::
        Make the program exit with codes similar to diff(1).
        That is, it exits with 1 if there were differences and
index 3b25d48098b99646819999bd29e64ade517419d6..8ec782dc54c9eb49873e38b75d925babe9a7746c 100755 (executable)
@@ -776,6 +776,7 @@ _git_diff ()
                        --no-ext-diff
                        --no-prefix --src-prefix= --dst-prefix=
                        --base --ours --theirs
+                       --inter-hunk-context=
                        "
                return
                ;;
@@ -967,6 +968,7 @@ _git_log ()
                        --color-words --walk-reflogs
                        --parents --children --full-history
                        --merge
+                       --inter-hunk-context=
                        "
                return
                ;;
diff --git a/diff.c b/diff.c
index c159a5fc658d762fba10800e5b828ad2f5c00b90..d23548292ad319defd691655409098f824ec9e94 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1469,6 +1469,7 @@ static void builtin_diff(const char *name_a,
                ecbdata.file = o->file;
                xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
                xecfg.ctxlen = o->context;
+               xecfg.interhunkctxlen = o->interhunkcontext;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
                if (pe)
                        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)
                options->b_prefix = arg + 13;
        else if (!strcmp(arg, "--no-prefix"))
                options->a_prefix = options->b_prefix = "";
+       else if (opt_arg(arg, '\0', "inter-hunk-context",
+                        &options->interhunkcontext))
+               ;
        else if (!prefixcmp(arg, "--output=")) {
                options->file = fopen(arg + strlen("--output="), "w");
                options->close_file = 1;
diff --git a/diff.h b/diff.h
index 42582edee68a4a4717ae5debebf37e6b9610fc8f..4d5a32781da81295d5aa1b4dd33dd2765be3ff89 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -78,6 +78,7 @@ struct diff_options {
        const char *a_prefix, *b_prefix;
        unsigned flags;
        int context;
+       int interhunkcontext;
        int break_opt;
        int detect_rename;
        int skip_stat_unmatch;
diff --git a/t/t4032-diff-inter-hunk-context.sh b/t/t4032-diff-inter-hunk-context.sh
new file mode 100755 (executable)
index 0000000..e4e3e28
--- /dev/null
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='diff hunk fusing'
+
+. ./test-lib.sh
+
+f() {
+       echo $1
+       i=1
+       while test $i -le $2
+       do
+               echo $i
+               i=$(expr $i + 1)
+       done
+       echo $3
+}
+
+t() {
+       case $# in
+       4) hunks=$4; cmd="diff -U$3";;
+       5) hunks=$5; cmd="diff -U$3 --inter-hunk-context=$4";;
+       esac
+       label="$cmd, $1 common $2"
+       file=f$1
+       expected=expected.$file.$3.$hunks
+
+       if ! test -f $file
+       then
+               f A $1 B >$file
+               git add $file
+               git commit -q -m. $file
+               f X $1 Y >$file
+       fi
+
+       test_expect_success "$label: count hunks ($hunks)" "
+               test $(git $cmd $file | grep '^@@ ' | wc -l) = $hunks
+       "
+
+       test -f $expected &&
+       test_expect_success "$label: check output" "
+               git $cmd $file | grep -v '^index ' >actual &&
+               test_cmp $expected actual
+       "
+}
+
+cat <<EOF >expected.f1.0.1 || exit 1
+diff --git a/f1 b/f1
+--- a/f1
++++ b/f1
+@@ -1,3 +1,3 @@
+-A
++X
+ 1
+-B
++Y
+EOF
+
+cat <<EOF >expected.f1.0.2 || exit 1
+diff --git a/f1 b/f1
+--- a/f1
++++ b/f1
+@@ -1 +1 @@
+-A
++X
+@@ -3 +3 @@ A
+-B
++Y
+EOF
+
+# common lines ctx     intrctx hunks
+t 1 line       0               2
+t 1 line       0       0       2
+t 1 line       0       1       1
+t 1 line       0       2       1
+t 1 line       1               1
+
+t 2 lines      0               2
+t 2 lines      0       0       2
+t 2 lines      0       1       2
+t 2 lines      0       2       1
+t 2 lines      1               1
+
+t 3 lines      1               2
+t 3 lines      1       0       2
+t 3 lines      1       1       1
+t 3 lines      1       2       1
+
+t 9 lines      3               2
+t 9 lines      3       2       2
+t 9 lines      3       3       1
+
+test_done
index 84fff583e2a6e3411da4260b9af98043fade1e49..361f80231905c66b642dcc764eeea32e7814ba07 100644 (file)
@@ -84,6 +84,7 @@ typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long
 
 typedef struct s_xdemitconf {
        long ctxlen;
+       long interhunkctxlen;
        unsigned long flags;
        find_func_t find_func;
        void *find_func_priv;
index 4625c1b4215231dc343478b2f4f7b4bfccf2c766..05bfa41f102801a5182e7fc642976f91e9ba7db6 100644 (file)
@@ -59,9 +59,10 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *
  */
 xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
        xdchange_t *xch, *xchp;
+       long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
 
        for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
-               if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen)
+               if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common)
                        break;
 
        return xchp;