diff: correctly disable external_diff with --no-ext-diff

Upon seeing a type-change filepair, "diff --no-ext-diff" does not show the usual "deletion followed by addition" split patch and does not run the external diff driver either. This is because the logic to disable external diff was placed at a wrong level in the callchain. run_diff_cmd() decides to show the split patch only when external diff driver is not configured or specified via GIT_EXTERNAL_DIFF environment, but this is done before checking if --no-ext-diff was given. To make things worse, run_diff_cmd() checks --no-ext-diff and disables the output for such a filepair completely, as the callchain below it (e.g. builtin_diff) does not want to handle typechange filepairs. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jul 17, 2012 at 22:08 UTC bd8c1a9b49933c766587c65de70a0b8ff518801f
2 files changed +24 -3
diff.c
+5 -3
@@ -2913,9 +2913,8 @@ static void run_diff_cmd(const char *pgm,
2913 int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score;
2914 int must_show_header = 0;
2915
2916 - if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
2917 - pgm = NULL;
2918 - else {
2916 +
2917 + if (DIFF_OPT_TST(o, ALLOW_EXTERNAL)) {
2918 struct userdiff_driver *drv = userdiff_find_by_path(attr_path);
2919 if (drv && drv->external)
2920 pgm = drv->external;
@@ -2995,6 +2994,9 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
2994 if (o->prefix_length)
2995 strip_prefix(o->prefix_length, &name, &other);
2996
2997 + if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
2998 + pgm = NULL;
2999 +
3000 if (DIFF_PAIR_UNMERGED(p)) {
3001 run_diff_cmd(pgm, name, NULL, attr_path,
3002 NULL, NULL, NULL, o, p);
t/t4020-diff-external.sh
+19
@@ -48,7 +48,26 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' '
48
49 '
50
51 +test_expect_success SYMLINKS 'typechange diff' '
52 + rm -f file &&
53 + ln -s elif file &&
54 + GIT_EXTERNAL_DIFF=echo git diff | {
55 + read path oldfile oldhex oldmode newfile newhex newmode &&
56 + test "z$path" = zfile &&
57 + test "z$oldmode" = z100644 &&
58 + test "z$newhex" = "z$_z40" &&
59 + test "z$newmode" = z120000 &&
60 + oh=$(git rev-parse --verify HEAD:file) &&
61 + test "z$oh" = "z$oldhex"
62 + } &&
63 + GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff >actual &&
64 + git diff >expect &&
65 + test_cmp expect actual
66 +'
67 +
68 test_expect_success 'diff attribute' '
69 + git reset --hard &&
70 + echo third >file &&
71
72 git config diff.parrot.command echo &&
73