diff: move no-index detection to builtin/diff.c
[gitweb.git] / builtin / diff.c
index adb93a9efa5ed9b97a08224e46f6fbaf680343e6..da69e4a3c81174cffe4d04b5531538b7d9fc78b2 100644 (file)
@@ -16,6 +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;
@@ -257,7 +260,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        int blobs = 0, paths = 0;
        const char *path = NULL;
        struct blobinfo blob[2];
-       int nongit;
+       int nongit = 0, no_index = 0;
        int result = 0;
 
        /*
@@ -283,14 +286,57 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
         * Other cases are errors.
         */
 
+       /* 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;
+       }
+
        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 <a> <b>", 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;
+
        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) {
+               if (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 <path> <path>",
+                              no_index == DIFF_NO_INDEX_EXPLICIT ?
+                                       "--no-index" : "[--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;