diff: make more cases implicit --no-index
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>
Sun, 25 Feb 2007 22:35:27 +0000 (23:35 +0100)
committerJunio C Hamano <junkio@cox.net>
Thu, 1 Mar 2007 00:32:31 +0000 (16:32 -0800)
When specifying an absolute path, or a relative path pointing outside
the working tree, do not fail, but roll your own diffopt parsing,
and execute a --no-index diff.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-diff-files.c
builtin-diff.c
diff-lib.c
diff.h

index e1199f80ae34a53872ca6a74ae9678053e33db14..aec83384298042fc4509605299f82e82745ae675 100644 (file)
@@ -23,7 +23,10 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
        git_config(git_default_config); /* no "diff" UI options */
        rev.abbrev = 0;
 
-       argc = setup_revisions(argc, argv, &rev, NULL);
+       if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))
+               argc = 0;
+       else
+               argc = setup_revisions(argc, argv, &rev, NULL);
        if (!rev.diffopt.output_format)
                rev.diffopt.output_format = DIFF_FORMAT_RAW;
        return run_diff_files_cmd(&rev, argc, argv);
index 28b660a780f9f2ae48acf5e8d3dc7c7aee178de2..4efbb8237bd49e8717a42833b2d9b2db064b45ac 100644 (file)
@@ -215,7 +215,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        git_config(git_diff_ui_config);
        init_revisions(&rev, prefix);
 
-       argc = setup_revisions(argc, argv, &rev, NULL);
+       if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))
+               argc = 0;
+       else
+               argc = setup_revisions(argc, argv, &rev, NULL);
        if (!rev.diffopt.output_format) {
                rev.diffopt.output_format = DIFF_FORMAT_PATCH;
                if (diff_setup_done(&rev.diffopt) < 0)
index 2e916199066db068d80ff5168b3feee6cfba7056..75ff0dd93d79ea77877151c50ae30580f1f00342 100644 (file)
@@ -200,6 +200,60 @@ static int handle_diff_files_args(struct rev_info *revs,
        return 0;
 }
 
+static int is_outside_repo(const char *path, int nongit, const char *prefix)
+{
+       int i;
+       if (nongit || !strcmp(path, "-") || path[0] == '/')
+               return 1;
+       if (prefixcmp(path, "../"))
+               return 0;
+       if (!prefix)
+               return 1;
+       for (i = strlen(prefix); !prefixcmp(path, "../"); ) {
+               while (i > 0 && prefix[i - 1] != '/')
+                       i--;
+               if (--i < 0)
+                       return 1;
+               path += 3;
+       }
+       return 0;
+}
+
+int setup_diff_no_index(struct rev_info *revs,
+               int argc, const char ** argv, int nongit, const char *prefix)
+{
+       int i;
+       for (i = 1; i < argc; i++)
+               if (argv[i][0] != '-')
+                       break;
+               else if (!strcmp(argv[i], "--")) {
+                       i++;
+                       break;
+               } else if (i < argc - 3 && !strcmp(argv[i], "--no-index")) {
+                       i = argc - 3;
+                       break;
+               }
+       if (argc != i + 2 || (!is_outside_repo(argv[i + 1], nongit, prefix) &&
+                               !is_outside_repo(argv[i], nongit, prefix)))
+               return -1;
+
+       diff_setup(&revs->diffopt);
+       for (i = 1; i < argc - 2; )
+               if (!strcmp(argv[i], "--no-index"))
+                       i++;
+               else {
+                       int j = diff_opt_parse(&revs->diffopt,
+                                       argv + i, argc - i);
+                       if (!j)
+                               die("invalid diff option/value: %s", argv[i]);
+                       i += j;
+               }
+       revs->diffopt.paths = argv + argc - 2;
+       revs->diffopt.nr_paths = 2;
+       revs->max_count = -2;
+       return 0;
+}
+
 int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
 {
        int silent_on_removed;
diff --git a/diff.h b/diff.h
index 4043cec04e0ae1da13a6049c9f30c4184f6b1da4..4b435e8b1933222da02f9e4cf2c28d2fef44d292 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -222,6 +222,8 @@ extern void diff_flush(struct diff_options*);
 extern const char *diff_unique_abbrev(const unsigned char *, int);
 
 extern int run_diff_files(struct rev_info *revs, int silent_on_removed);
+extern int setup_diff_no_index(struct rev_info *revs,
+               int argc, const char ** argv, int nongit, const char *prefix);
 extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv);
 
 extern int run_diff_index(struct rev_info *revs, int cached);