From: Junio C Hamano Date: Fri, 27 Dec 2013 22:58:17 +0000 (-0800) Subject: Merge branch 'tg/diff-no-index-refactor' X-Git-Tag: v1.9-rc0~49 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/73b063130befa7475316a142343de87da61f31e3?ds=inline;hp=-c Merge branch 'tg/diff-no-index-refactor' "git diff ../else/where/A ../else/where/B" when ../else/where is clearly outside the repository, and "git diff --no-index A B", do not have to look at the index at all, but we used to read the index unconditionally. * tg/diff-no-index-refactor: diff: avoid some nesting diff: add test for --no-index executed outside repo diff: don't read index when --no-index is given diff: move no-index detection to builtin/diff.c --- 73b063130befa7475316a142343de87da61f31e3 diff --combined builtin/diff.c index fe0cc7f1b5,24d6271625..0f247d2400 --- a/builtin/diff.c +++ b/builtin/diff.c @@@ -16,6 -16,9 +16,9 @@@ #include "submodule.h" #include "sha1-array.h" + #define DIFF_NO_INDEX_EXPLICIT 1 + #define DIFF_NO_INDEX_IMPLICIT 2 + struct blobinfo { unsigned char sha1[20]; const char *name; @@@ -64,18 -67,15 +67,18 @@@ static void stuff_change(struct diff_op static int builtin_diff_b_f(struct rev_info *revs, int argc, const char **argv, - struct blobinfo *blob, - const char *path) + struct blobinfo *blob) { /* Blob vs file in the working tree*/ struct stat st; + const char *path; if (argc > 1) usage(builtin_diff_usage); + GUARD_PATHSPEC(&revs->prune_data, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); + path = revs->prune_data.items[0].match; + if (lstat(path, &st)) die_errno(_("failed to stat '%s'"), path); if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) @@@ -258,8 -258,9 +261,8 @@@ int cmd_diff(int argc, const char **arg struct rev_info rev; struct object_array ent = OBJECT_ARRAY_INIT; int blobs = 0, paths = 0; - const char *path = NULL; struct blobinfo blob[2]; - int nongit; + int nongit = 0, no_index = 0; int result = 0; /* @@@ -285,14 -286,59 +288,59 @@@ * Other cases are errors. */ - prefix = setup_git_directory_gently(&nongit); - gitmodules_config(); + /* Were we asked to do --no-index explicitly? */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--")) { + i++; + break; + } + if (!strcmp(argv[i], "--no-index")) + no_index = DIFF_NO_INDEX_EXPLICIT; + if (argv[i][0] != '-') + break; + } + + if (!no_index) + prefix = setup_git_directory_gently(&nongit); + + /* + * Treat git diff with at least one path outside of the + * repo the same as if the command would have been executed + * outside of a git repository. In this case it behaves + * the same way as "git diff --no-index ", which acts + * as a colourful "diff" replacement. + */ + if (nongit || ((argc == i + 2) && + (!path_inside_repo(prefix, argv[i]) || + !path_inside_repo(prefix, argv[i + 1])))) + no_index = DIFF_NO_INDEX_IMPLICIT; + + if (!no_index) + gitmodules_config(); git_config(git_diff_ui_config, NULL); init_revisions(&rev, prefix); - /* If this is a no-index diff, just run it and exit there. */ - diff_no_index(&rev, argc, argv, nongit, prefix); + if (no_index && argc != i + 2) { + if (no_index == DIFF_NO_INDEX_IMPLICIT) { + /* + * There was no --no-index and there were not two + * paths. It is possible that the user intended + * to do an inside-repository operation. + */ + fprintf(stderr, "Not a git repository\n"); + fprintf(stderr, + "To compare two paths outside a working tree:\n"); + } + /* Give the usage message for non-repository usage and exit. */ + usagef("git diff %s ", + no_index == DIFF_NO_INDEX_EXPLICIT ? + "--no-index" : "[--no-index]"); + + } + if (no_index) + /* If this is a no-index diff, just run it and exit there. */ + diff_no_index(&rev, argc, argv, prefix); /* Otherwise, we are doing the usual "git" diff */ rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; @@@ -368,8 -414,13 +416,8 @@@ die(_("unhandled object '%s' given."), name); } } - if (rev.prune_data.nr) { - /* builtin_diff_b_f() */ - GUARD_PATHSPEC(&rev.prune_data, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); - if (!path) - path = rev.prune_data.items[0].match; + if (rev.prune_data.nr) paths += rev.prune_data.nr; - } /* * Now, do the arguments look reasonable? @@@ -382,7 -433,7 +430,7 @@@ case 1: if (paths != 1) usage(builtin_diff_usage); - result = builtin_diff_b_f(&rev, argc, argv, blob, path); + result = builtin_diff_b_f(&rev, argc, argv, blob); break; case 2: if (paths) diff --combined diff.h index 760388fa17,de105d392a..ce123fa06f --- a/diff.h +++ b/diff.h @@@ -164,8 -164,6 +164,8 @@@ struct diff_options diff_prefix_fn_t output_prefix; int output_prefix_length; void *output_prefix_data; + + int diff_path_counter; }; enum color_diff { @@@ -246,7 -244,7 +246,7 @@@ extern struct diff_filepair *diff_unmer #define DIFF_SETUP_USE_SIZE_CACHE 4 /* - * Poor man's alternative to parse-option, to allow both sticked form + * Poor man's alternative to parse-option, to allow both stuck form * (--option=value) and separate form (--option value). */ extern int parse_long_opt(const char *opt, const char **argv, @@@ -332,7 -330,7 +332,7 @@@ extern int diff_flush_patch_id(struct d extern int diff_result_code(struct diff_options *, int); - extern void diff_no_index(struct rev_info *, int, const char **, int, const char *); + extern void diff_no_index(struct rev_info *, int, const char **, const char *); extern int index_differs_from(const char *def, int diff_flags);