summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin-diff-files.c5
-rw-r--r--builtin-diff.c5
-rw-r--r--diff-lib.c54
-rw-r--r--diff.h2
4 files changed, 64 insertions, 2 deletions
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index e1199f80ae..aec8338429 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -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);
diff --git a/builtin-diff.c b/builtin-diff.c
index 28b660a780..4efbb8237b 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -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)
diff --git a/diff-lib.c b/diff-lib.c
index 2e91619906..75ff0dd93d 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -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 4043cec04e..4b435e8b19 100644
--- 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);