"git diff": do not ignore index without --no-index
Even if "foo" and/or "bar" does not exist in index, "git diff foo bar" should not change behaviour drastically from "git diff foo bar baz" or "git diff foo". A feature that "sometimes works and is handy" is an unreliable cute hack. "git diff foo bar" outside a git repository continues to work as a more colourful alternative to "diff -u" as before. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
May 23, 2008 at 22:28 UTC
0569e9b8cea20d5eedfec66730a9711a0907ab0d
8 files changed
+283
-338
Makefile
+1
@@ -405,6 +405,7 @@ LIB_OBJS += diffcore-order.o
405
LIB_OBJS += diffcore-pickaxe.o
406
LIB_OBJS += diffcore-rename.o
407
LIB_OBJS += diff-delta.o
408
+LIB_OBJS += diff-no-index.o
409
LIB_OBJS += diff-lib.o
410
LIB_OBJS += diff.o
411
LIB_OBJS += dir.o
builtin-diff.c
+45
-10
@@ -202,6 +202,37 @@ static void refresh_index_quietly(void)
202
rollback_lock_file(lock_file);
203
}
204
205
+static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
206
+{
207
+ int result;
208
+ unsigned int options = 0;
209
+
210
+ while (1 < argc && argv[1][0] == '-') {
211
+ if (!strcmp(argv[1], "--base"))
212
+ revs->max_count = 1;
213
+ else if (!strcmp(argv[1], "--ours"))
214
+ revs->max_count = 2;
215
+ else if (!strcmp(argv[1], "--theirs"))
216
+ revs->max_count = 3;
217
+ else if (!strcmp(argv[1], "-q"))
218
+ options |= DIFF_SILENT_ON_REMOVED;
219
+ else
220
+ return error("invalid option: %s", argv[1]);
221
+ argv++; argc--;
222
+ }
223
+
224
+ if (revs->max_count == -1 &&
225
+ (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
226
+ revs->combine_merges = revs->dense_combined_merges = 1;
227
+
228
+ if (read_cache() < 0) {
229
+ perror("read_cache");
230
+ return -1;
231
+ }
232
+ result = run_diff_files(revs, options);
233
+ return diff_result_code(&revs->diffopt, result);
234
+}
235
+
236
int cmd_diff(int argc, const char **argv, const char *prefix)
237
{
238
int i;
@@ -230,6 +261,9 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
261
* N=2, M=0:
262
* tree vs tree (diff-tree)
263
*
264
+ * N=0, M=0, P=2:
265
+ * compare two filesystem entities (aka --no-index).
266
+ *
267
* Other cases are errors.
268
*/
269
@@ -240,21 +274,21 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
274
diff_use_color_default = git_use_color_default;
275
276
init_revisions(&rev, prefix);
277
+
278
+ /* If this is a no-index diff, just run it and exit there. */
279
+ diff_no_index(&rev, argc, argv, nongit, prefix);
280
+
281
+ /* Otherwise, we are doing the usual "git" diff */
282
rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
283
245
- if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))
246
- argc = 0;
247
- else
248
- argc = setup_revisions(argc, argv, &rev, NULL);
284
+ if (nongit)
285
+ die("Not a git repository");
286
+ argc = setup_revisions(argc, argv, &rev, NULL);
287
if (!rev.diffopt.output_format) {
288
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
289
if (diff_setup_done(&rev.diffopt) < 0)
290
die("diff_setup_done failed");
291
}
254
- if (rev.diffopt.prefix && nongit) {
255
- rev.diffopt.prefix = NULL;
256
- rev.diffopt.prefix_length = 0;
257
- }
292
DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
293
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
294
@@ -265,7 +299,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
299
if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS))
300
setup_pager();
301
268
- /* Do we have --cached and not have a pending object, then
302
+ /*
303
+ * Do we have --cached and not have a pending object, then
304
* default to HEAD by hand. Eek.
305
*/
306
if (!rev.pending.nr) {
@@ -333,7 +368,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
368
if (!ents) {
369
switch (blobs) {
370
case 0:
336
- result = run_diff_files_cmd(&rev, argc, argv);
371
+ result = builtin_diff_files(&rev, argc, argv);
372
break;
373
case 1:
374
if (paths != 1)
diff-lib.c
-323
@@ -8,7 +8,6 @@
8
#include "diffcore.h"
9
#include "revision.h"
10
#include "cache-tree.h"
11
-#include "path-list.h"
11
#include "unpack-trees.h"
12
#include "refs.h"
13
@@ -16,328 +15,6 @@
15
* diff-files
16
*/
17
19
-static int read_directory(const char *path, struct path_list *list)
20
-{
21
- DIR *dir;
22
- struct dirent *e;
23
-
24
- if (!(dir = opendir(path)))
25
- return error("Could not open directory %s", path);
26
-
27
- while ((e = readdir(dir)))
28
- if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
29
- path_list_insert(e->d_name, list);
30
-
31
- closedir(dir);
32
- return 0;
33
-}
34
-
35
-static int get_mode(const char *path, int *mode)
36
-{
37
- struct stat st;
38
-
39
- if (!path || !strcmp(path, "/dev/null"))
40
- *mode = 0;
41
- else if (!strcmp(path, "-"))
42
- *mode = create_ce_mode(0666);
43
- else if (stat(path, &st))
44
- return error("Could not access '%s'", path);
45
- else
46
- *mode = st.st_mode;
47
- return 0;
48
-}
49
-
50
-static int queue_diff(struct diff_options *o,
51
- const char *name1, const char *name2)
52
-{
53
- int mode1 = 0, mode2 = 0;
54
-
55
- if (get_mode(name1, &mode1) || get_mode(name2, &mode2))
56
- return -1;
57
-
58
- if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
59
- return error("file/directory conflict: %s, %s", name1, name2);
60
-
61
- if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
62
- char buffer1[PATH_MAX], buffer2[PATH_MAX];
63
- struct path_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
64
- int len1 = 0, len2 = 0, i1, i2, ret = 0;
65
-
66
- if (name1 && read_directory(name1, &p1))
67
- return -1;
68
- if (name2 && read_directory(name2, &p2)) {
69
- path_list_clear(&p1, 0);
70
- return -1;
71
- }
72
-
73
- if (name1) {
74
- len1 = strlen(name1);
75
- if (len1 > 0 && name1[len1 - 1] == '/')
76
- len1--;
77
- memcpy(buffer1, name1, len1);
78
- buffer1[len1++] = '/';
79
- }
80
-
81
- if (name2) {
82
- len2 = strlen(name2);
83
- if (len2 > 0 && name2[len2 - 1] == '/')
84
- len2--;
85
- memcpy(buffer2, name2, len2);
86
- buffer2[len2++] = '/';
87
- }
88
-
89
- for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
90
- const char *n1, *n2;
91
- int comp;
92
-
93
- if (i1 == p1.nr)
94
- comp = 1;
95
- else if (i2 == p2.nr)
96
- comp = -1;
97
- else
98
- comp = strcmp(p1.items[i1].path,
99
- p2.items[i2].path);
100
-
101
- if (comp > 0)
102
- n1 = NULL;
103
- else {
104
- n1 = buffer1;
105
- strncpy(buffer1 + len1, p1.items[i1++].path,
106
- PATH_MAX - len1);
107
- }
108
-
109
- if (comp < 0)
110
- n2 = NULL;
111
- else {
112
- n2 = buffer2;
113
- strncpy(buffer2 + len2, p2.items[i2++].path,
114
- PATH_MAX - len2);
115
- }
116
-
117
- ret = queue_diff(o, n1, n2);
118
- }
119
- path_list_clear(&p1, 0);
120
- path_list_clear(&p2, 0);
121
-
122
- return ret;
123
- } else {
124
- struct diff_filespec *d1, *d2;
125
-
126
- if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
127
- unsigned tmp;
128
- const char *tmp_c;
129
- tmp = mode1; mode1 = mode2; mode2 = tmp;
130
- tmp_c = name1; name1 = name2; name2 = tmp_c;
131
- }
132
-
133
- if (!name1)
134
- name1 = "/dev/null";
135
- if (!name2)
136
- name2 = "/dev/null";
137
- d1 = alloc_filespec(name1);
138
- d2 = alloc_filespec(name2);
139
- fill_filespec(d1, null_sha1, mode1);
140
- fill_filespec(d2, null_sha1, mode2);
141
-
142
- diff_queue(&diff_queued_diff, d1, d2);
143
- return 0;
144
- }
145
-}
146
-
147
-/*
148
- * Does the path name a blob in the working tree, or a directory
149
- * in the working tree?
150
- */
151
-static int is_in_index(const char *path)
152
-{
153
- int len, pos;
154
- struct cache_entry *ce;
155
-
156
- len = strlen(path);
157
- while (path[len-1] == '/')
158
- len--;
159
- if (!len)
160
- return 1; /* "." */
161
- pos = cache_name_pos(path, len);
162
- if (0 <= pos)
163
- return 1;
164
- pos = -1 - pos;
165
- while (pos < active_nr) {
166
- ce = active_cache[pos++];
167
- if (ce_namelen(ce) <= len ||
168
- strncmp(ce->name, path, len) ||
169
- (ce->name[len] > '/'))
170
- break; /* path cannot be a prefix */
171
- if (ce->name[len] == '/')
172
- return 1;
173
- }
174
- return 0;
175
-}
176
-
177
-static int handle_diff_files_args(struct rev_info *revs,
178
- int argc, const char **argv,
179
- unsigned int *options)
180
-{
181
- *options = 0;
182
-
183
- /* revs->max_count == -2 means --no-index */
184
- while (1 < argc && argv[1][0] == '-') {
185
- if (!strcmp(argv[1], "--base"))
186
- revs->max_count = 1;
187
- else if (!strcmp(argv[1], "--ours"))
188
- revs->max_count = 2;
189
- else if (!strcmp(argv[1], "--theirs"))
190
- revs->max_count = 3;
191
- else if (!strcmp(argv[1], "-n") ||
192
- !strcmp(argv[1], "--no-index")) {
193
- revs->max_count = -2;
194
- DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
195
- DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
196
- }
197
- else if (!strcmp(argv[1], "-q"))
198
- *options |= DIFF_SILENT_ON_REMOVED;
199
- else
200
- return error("invalid option: %s", argv[1]);
201
- argv++; argc--;
202
- }
203
-
204
- if (revs->max_count == -1 && revs->diffopt.nr_paths == 2) {
205
- /*
206
- * If two files are specified, and at least one is untracked,
207
- * default to no-index.
208
- */
209
- read_cache();
210
- if (!is_in_index(revs->diffopt.paths[0]) ||
211
- !is_in_index(revs->diffopt.paths[1])) {
212
- revs->max_count = -2;
213
- DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
214
- }
215
- }
216
-
217
- /*
218
- * Make sure there are NO revision (i.e. pending object) parameter,
219
- * rev.max_count is reasonable (0 <= n <= 3),
220
- * there is no other revision filtering parameters.
221
- */
222
- if (revs->pending.nr || revs->max_count > 3 ||
223
- revs->min_age != -1 || revs->max_age != -1)
224
- return error("no revision allowed with diff-files");
225
-
226
- if (revs->max_count == -1 &&
227
- (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
228
- revs->combine_merges = revs->dense_combined_merges = 1;
229
-
230
- return 0;
231
-}
232
-
233
-static int is_outside_repo(const char *path, int nongit, const char *prefix)
234
-{
235
- int i;
236
- if (nongit || !strcmp(path, "-") || is_absolute_path(path))
237
- return 1;
238
- if (prefixcmp(path, "../"))
239
- return 0;
240
- if (!prefix)
241
- return 1;
242
- for (i = strlen(prefix); !prefixcmp(path, "../"); ) {
243
- while (i > 0 && prefix[i - 1] != '/')
244
- i--;
245
- if (--i < 0)
246
- return 1;
247
- path += 3;
248
- }
249
- return 0;
250
-}
251
-
252
-int setup_diff_no_index(struct rev_info *revs,
253
- int argc, const char ** argv, int nongit, const char *prefix)
254
-{
255
- int i;
256
- for (i = 1; i < argc; i++)
257
- if (argv[i][0] != '-' || argv[i][1] == '\0')
258
- break;
259
- else if (!strcmp(argv[i], "--")) {
260
- i++;
261
- break;
262
- } else if (i < argc - 3 && !strcmp(argv[i], "--no-index")) {
263
- i = argc - 3;
264
- DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
265
- break;
266
- }
267
- if (nongit && argc != i + 2)
268
- die("git diff [--no-index] takes two paths");
269
-
270
- if (argc != i + 2 || (!is_outside_repo(argv[i + 1], nongit, prefix) &&
271
- !is_outside_repo(argv[i], nongit, prefix)))
272
- return -1;
273
-
274
- diff_setup(&revs->diffopt);
275
- for (i = 1; i < argc - 2; )
276
- if (!strcmp(argv[i], "--no-index"))
277
- i++;
278
- else {
279
- int j = diff_opt_parse(&revs->diffopt,
280
- argv + i, argc - i);
281
- if (!j)
282
- die("invalid diff option/value: %s", argv[i]);
283
- i += j;
284
- }
285
-
286
- if (prefix) {
287
- int len = strlen(prefix);
288
-
289
- revs->diffopt.paths = xcalloc(2, sizeof(char*));
290
- for (i = 0; i < 2; i++) {
291
- const char *p = argv[argc - 2 + i];
292
- /*
293
- * stdin should be spelled as '-'; if you have
294
- * path that is '-', spell it as ./-.
295
- */
296
- p = (strcmp(p, "-")
297
- ? xstrdup(prefix_filename(prefix, len, p))
298
- : p);
299
- revs->diffopt.paths[i] = p;
300
- }
301
- }
302
- else
303
- revs->diffopt.paths = argv + argc - 2;
304
- revs->diffopt.nr_paths = 2;
305
- DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
306
- revs->max_count = -2;
307
- if (diff_setup_done(&revs->diffopt) < 0)
308
- die("diff_setup_done failed");
309
- return 0;
310
-}
311
-
312
-int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
313
-{
314
- unsigned int options;
315
-
316
- if (handle_diff_files_args(revs, argc, argv, &options))
317
- return -1;
318
-
319
- if (DIFF_OPT_TST(&revs->diffopt, NO_INDEX)) {
320
- if (revs->diffopt.nr_paths != 2)
321
- return error("need two files/directories with --no-index");
322
- if (queue_diff(&revs->diffopt, revs->diffopt.paths[0],
323
- revs->diffopt.paths[1]))
324
- return -1;
325
- diffcore_std(&revs->diffopt);
326
- diff_flush(&revs->diffopt);
327
- /*
328
- * The return code for --no-index imitates diff(1):
329
- * 0 = no changes, 1 = changes, else error
330
- */
331
- return revs->diffopt.found_changes;
332
- }
333
-
334
- if (read_cache() < 0) {
335
- perror("read_cache");
336
- return -1;
337
- }
338
- return run_diff_files(revs, options);
339
-}
340
-
18
/*
19
* Has the work tree entity been removed?
20
*
diff-no-index.c
new
+231
@@ -0,0 +1,231 @@
1
+/*
2
+ * "diff --no-index" support
3
+ * Copyright (c) 2007 by Johannes Schindelin
4
+ * Copyright (c) 2008 by Junio C Hamano
5
+ */
6
+
7
+#include "cache.h"
8
+#include "color.h"
9
+#include "commit.h"
10
+#include "blob.h"
11
+#include "tag.h"
12
+#include "diff.h"
13
+#include "diffcore.h"
14
+#include "revision.h"
15
+#include "log-tree.h"
16
+#include "builtin.h"
17
+#include "path-list.h"
18
+
19
+static int read_directory(const char *path, struct path_list *list)
20
+{
21
+ DIR *dir;
22
+ struct dirent *e;
23
+
24
+ if (!(dir = opendir(path)))
25
+ return error("Could not open directory %s", path);
26
+
27
+ while ((e = readdir(dir)))
28
+ if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
29
+ path_list_insert(e->d_name, list);
30
+
31
+ closedir(dir);
32
+ return 0;
33
+}
34
+
35
+static int get_mode(const char *path, int *mode)
36
+{
37
+ struct stat st;
38
+
39
+ if (!path || !strcmp(path, "/dev/null"))
40
+ *mode = 0;
41
+ else if (!strcmp(path, "-"))
42
+ *mode = create_ce_mode(0666);
43
+ else if (stat(path, &st))
44
+ return error("Could not access '%s'", path);
45
+ else
46
+ *mode = st.st_mode;
47
+ return 0;
48
+}
49
+
50
+static int queue_diff(struct diff_options *o,
51
+ const char *name1, const char *name2)
52
+{
53
+ int mode1 = 0, mode2 = 0;
54
+
55
+ if (get_mode(name1, &mode1) || get_mode(name2, &mode2))
56
+ return -1;
57
+
58
+ if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
59
+ return error("file/directory conflict: %s, %s", name1, name2);
60
+
61
+ if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
62
+ char buffer1[PATH_MAX], buffer2[PATH_MAX];
63
+ struct path_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
64
+ int len1 = 0, len2 = 0, i1, i2, ret = 0;
65
+
66
+ if (name1 && read_directory(name1, &p1))
67
+ return -1;
68
+ if (name2 && read_directory(name2, &p2)) {
69
+ path_list_clear(&p1, 0);
70
+ return -1;
71
+ }
72
+
73
+ if (name1) {
74
+ len1 = strlen(name1);
75
+ if (len1 > 0 && name1[len1 - 1] == '/')
76
+ len1--;
77
+ memcpy(buffer1, name1, len1);
78
+ buffer1[len1++] = '/';
79
+ }
80
+
81
+ if (name2) {
82
+ len2 = strlen(name2);
83
+ if (len2 > 0 && name2[len2 - 1] == '/')
84
+ len2--;
85
+ memcpy(buffer2, name2, len2);
86
+ buffer2[len2++] = '/';
87
+ }
88
+
89
+ for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
90
+ const char *n1, *n2;
91
+ int comp;
92
+
93
+ if (i1 == p1.nr)
94
+ comp = 1;
95
+ else if (i2 == p2.nr)
96
+ comp = -1;
97
+ else
98
+ comp = strcmp(p1.items[i1].path,
99
+ p2.items[i2].path);
100
+
101
+ if (comp > 0)
102
+ n1 = NULL;
103
+ else {
104
+ n1 = buffer1;
105
+ strncpy(buffer1 + len1, p1.items[i1++].path,
106
+ PATH_MAX - len1);
107
+ }
108
+
109
+ if (comp < 0)
110
+ n2 = NULL;
111
+ else {
112
+ n2 = buffer2;
113
+ strncpy(buffer2 + len2, p2.items[i2++].path,
114
+ PATH_MAX - len2);
115
+ }
116
+
117
+ ret = queue_diff(o, n1, n2);
118
+ }
119
+ path_list_clear(&p1, 0);
120
+ path_list_clear(&p2, 0);
121
+
122
+ return ret;
123
+ } else {
124
+ struct diff_filespec *d1, *d2;
125
+
126
+ if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
127
+ unsigned tmp;
128
+ const char *tmp_c;
129
+ tmp = mode1; mode1 = mode2; mode2 = tmp;
130
+ tmp_c = name1; name1 = name2; name2 = tmp_c;
131
+ }
132
+
133
+ if (!name1)
134
+ name1 = "/dev/null";
135
+ if (!name2)
136
+ name2 = "/dev/null";
137
+ d1 = alloc_filespec(name1);
138
+ d2 = alloc_filespec(name2);
139
+ fill_filespec(d1, null_sha1, mode1);
140
+ fill_filespec(d2, null_sha1, mode2);
141
+
142
+ diff_queue(&diff_queued_diff, d1, d2);
143
+ return 0;
144
+ }
145
+}
146
+
147
+void diff_no_index(struct rev_info *revs,
148
+ int argc, const char **argv,
149
+ int nongit, const char *prefix)
150
+{
151
+ int i;
152
+ int no_index = 0;
153
+ unsigned options = 0;
154
+
155
+ /* Were we asked to do --no-index explicitly? */
156
+ for (i = 1; i < argc; i++) {
157
+ if (!strcmp(argv[i], "--"))
158
+ return;
159
+ if (!strcmp(argv[i], "--no-index"))
160
+ no_index = 1;
161
+ if (argv[i][0] != '-')
162
+ break;
163
+ }
164
+
165
+ /*
166
+ * No explicit --no-index, but "git diff --opts A B" outside
167
+ * a git repository is a cute hack to support.
168
+ */
169
+ if (!no_index && !nongit)
170
+ return;
171
+
172
+ if (argc != i + 2)
173
+ die("git diff %s takes two paths",
174
+ no_index ? "--no-index" : "[--no-index]");
175
+
176
+ diff_setup(&revs->diffopt);
177
+ if (!revs->diffopt.output_format)
178
+ revs->diffopt.output_format = DIFF_FORMAT_PATCH;
179
+ for (i = 1; i < argc - 2; ) {
180
+ int j;
181
+ if (!strcmp(argv[i], "--no-index"))
182
+ i++;
183
+ else if (!strcmp(argv[1], "-q"))
184
+ options |= DIFF_SILENT_ON_REMOVED;
185
+ else {
186
+ j = diff_opt_parse(&revs->diffopt, argv + i, argc - i);
187
+ if (!j)
188
+ die("invalid diff option/value: %s", argv[i]);
189
+ i += j;
190
+ }
191
+ }
192
+
193
+ if (prefix) {
194
+ int len = strlen(prefix);
195
+
196
+ revs->diffopt.paths = xcalloc(2, sizeof(char*));
197
+ for (i = 0; i < 2; i++) {
198
+ const char *p = argv[argc - 2 + i];
199
+ /*
200
+ * stdin should be spelled as '-'; if you have
201
+ * path that is '-', spell it as ./-.
202
+ */
203
+ p = (strcmp(p, "-")
204
+ ? xstrdup(prefix_filename(prefix, len, p))
205
+ : p);
206
+ revs->diffopt.paths[i] = p;
207
+ }
208
+ }
209
+ else
210
+ revs->diffopt.paths = argv + argc - 2;
211
+ revs->diffopt.nr_paths = 2;
212
+
213
+ DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
214
+ DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
215
+
216
+ revs->max_count = -2;
217
+ if (diff_setup_done(&revs->diffopt) < 0)
218
+ die("diff_setup_done failed");
219
+
220
+ if (queue_diff(&revs->diffopt, revs->diffopt.paths[0],
221
+ revs->diffopt.paths[1]))
222
+ exit(1);
223
+ diffcore_std(&revs->diffopt);
224
+ diff_flush(&revs->diffopt);
225
+
226
+ /*
227
+ * The return code for --no-index imitates diff(1):
228
+ * 0 = no changes, 1 = changes, else error
229
+ */
230
+ exit(revs->diffopt.found_changes);
231
+}
diff.h
+2
-4
@@ -250,10 +250,6 @@ extern const char *diff_unique_abbrev(const unsigned char *, int);
250
/* report racily-clean paths as modified */
251
#define DIFF_RACY_IS_MODIFIED 02
252
extern int run_diff_files(struct rev_info *revs, unsigned int option);
253
-extern int setup_diff_no_index(struct rev_info *revs,
254
- int argc, const char ** argv, int nongit, const char *prefix);
255
-extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv);
256
-
253
extern int run_diff_index(struct rev_info *revs, int cached);
254
255
extern int do_diff_cache(const unsigned char *, struct diff_options *);
@@ -261,4 +257,6 @@ extern int diff_flush_patch_id(struct diff_options *, unsigned char *);
257
258
extern int diff_result_code(struct diff_options *, int);
259
260
+extern void diff_no_index(struct rev_info *, int, const char **, int, const char *);
261
+
262
#endif /* DIFF_H */
t/t4013-diff-various.sh
+1
@@ -257,6 +257,7 @@ diff --patch-with-raw initial..side
257
diff --patch-with-stat -r initial..side
258
diff --patch-with-raw -r initial..side
259
diff --name-status dir2 dir
260
+diff --no-index --name-status dir2 dir
261
EOF
262
263
test_done
t/t4013/diff.diff_--name-status_dir2_dir
-1
@@ -1,3 +1,2 @@
1
$ git diff --name-status dir2 dir
2
-A dir/sub
2
$
t/t4013/diff.diff_--no-index_--name-status_dir2_dir
new
+3
@@ -0,0 +1,3 @@
1
+$ git diff --no-index --name-status dir2 dir
2
+A dir/sub
3
+$