diff: reuse diff setup for --no-index case

When "--no-index" is in effect (or implied by the arguments), git-diff jumps early to a special code path to perform that diff. This means we miss out on some settings like enabling --ext-diff and --textconv by default. Let's jump to the no-index path _after_ we've done more setup on rev.diffopt. Since some of the options don't affect us (e.g., items related to the index), let's re-order the setup into two blocks (see the in-code comments). Note that we also need to stop re-initializing the diffopt struct in diff_no_index(). This should not be necessary, as it will already have been initialized by cmd_diff() (and there are no other callers). That in turn lets us drop the "repository" argument from diff_no_index (which never made much sense, since the whole point is that you don't need a repository). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Feb 16, 2019 at 01:57 UTC 287ab28bfae14431f3f57abeb92149c460044850
4 files changed +21 -17
builtin/diff.c
+11 -9
@@ -337,21 +337,23 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
337 "--no-index" : "[--no-index]");
338
339 }
340 - if (no_index)
341 - /* If this is a no-index diff, just run it and exit there. */
342 - diff_no_index(the_repository, &rev, argc, argv);
343 -
344 - /* Otherwise, we are doing the usual "git" diff */
345 - rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
340
347 - /* Scale to real terminal size and respect statGraphWidth config */
341 + /* Set up defaults that will apply to both no-index and regular diffs. */
342 rev.diffopt.stat_width = -1;
343 rev.diffopt.stat_graph_width = -1;
350 -
351 - /* Default to let external and textconv be used */
344 rev.diffopt.flags.allow_external = 1;
345 rev.diffopt.flags.allow_textconv = 1;
346
347 + /* If this is a no-index diff, just run it and exit there. */
348 + if (no_index)
349 + diff_no_index(&rev, argc, argv);
350 +
351 + /*
352 + * Otherwise, we are doing the usual "git" diff; set up any
353 + * further defaults that apply to regular diffs.
354 + */
355 + rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
356 +
357 /*
358 * Default to intent-to-add entries invisible in the
359 * index. This makes them show up as new files in diff-files
diff-no-index.c
+1 -7
@@ -233,8 +233,7 @@ static void fixup_paths(const char **path, struct strbuf *replacement)
233 }
234 }
235
236 -void diff_no_index(struct repository *r,
237 - struct rev_info *revs,
236 +void diff_no_index(struct rev_info *revs,
237 int argc, const char **argv)
238 {
239 int i;
@@ -242,11 +241,6 @@ void diff_no_index(struct repository *r,
241 struct strbuf replacement = STRBUF_INIT;
242 const char *prefix = revs->prefix;
243
245 - /*
246 - * FIXME: --no-index should not look at index and we should be
247 - * able to pass NULL repo. Maybe later.
248 - */
249 - repo_diff_setup(r, &revs->diffopt);
244 for (i = 1; i < argc - 2; ) {
245 int j;
246 if (!strcmp(argv[i], "--no-index"))
diff.h
+1 -1
@@ -434,7 +434,7 @@ int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
434
435 int diff_result_code(struct diff_options *, int);
436
437 -void diff_no_index(struct repository *, struct rev_info *, int, const char **);
437 +void diff_no_index(struct rev_info *, int, const char **);
438
439 int index_differs_from(const char *def, const struct diff_flags *flags,
440 int ita_invisible_in_index);
t/t4053-diff-no-index.sh
+8
@@ -137,4 +137,12 @@ test_expect_success 'diff --no-index from repo subdir with absolute paths' '
137 test_cmp expect actual
138 '
139
140 +test_expect_success 'diff --no-index allows external diff' '
141 + test_expect_code 1 \
142 + env GIT_EXTERNAL_DIFF="echo external ;:" \
143 + git diff --no-index non/git/a non/git/b >actual &&
144 + echo external >expect &&
145 + test_cmp expect actual
146 +'
147 +
148 test_done