Git fork

"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>

+283 -338
+1
Makefile
··· 405 405 LIB_OBJS += diffcore-pickaxe.o 406 406 LIB_OBJS += diffcore-rename.o 407 407 LIB_OBJS += diff-delta.o 408 + LIB_OBJS += diff-no-index.o 408 409 LIB_OBJS += diff-lib.o 409 410 LIB_OBJS += diff.o 410 411 LIB_OBJS += dir.o
+45 -10
builtin-diff.c
··· 202 202 rollback_lock_file(lock_file); 203 203 } 204 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 + 205 236 int cmd_diff(int argc, const char **argv, const char *prefix) 206 237 { 207 238 int i; ··· 230 261 * N=2, M=0: 231 262 * tree vs tree (diff-tree) 232 263 * 264 + * N=0, M=0, P=2: 265 + * compare two filesystem entities (aka --no-index). 266 + * 233 267 * Other cases are errors. 234 268 */ 235 269 ··· 240 274 diff_use_color_default = git_use_color_default; 241 275 242 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 */ 243 282 rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; 244 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); 249 287 if (!rev.diffopt.output_format) { 250 288 rev.diffopt.output_format = DIFF_FORMAT_PATCH; 251 289 if (diff_setup_done(&rev.diffopt) < 0) 252 290 die("diff_setup_done failed"); 253 291 } 254 - if (rev.diffopt.prefix && nongit) { 255 - rev.diffopt.prefix = NULL; 256 - rev.diffopt.prefix_length = 0; 257 - } 258 292 DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL); 259 293 DIFF_OPT_SET(&rev.diffopt, RECURSIVE); 260 294 ··· 265 299 if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) 266 300 setup_pager(); 267 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 269 304 * default to HEAD by hand. Eek. 270 305 */ 271 306 if (!rev.pending.nr) { ··· 333 368 if (!ents) { 334 369 switch (blobs) { 335 370 case 0: 336 - result = run_diff_files_cmd(&rev, argc, argv); 371 + result = builtin_diff_files(&rev, argc, argv); 337 372 break; 338 373 case 1: 339 374 if (paths != 1)
-323
diff-lib.c
··· 8 8 #include "diffcore.h" 9 9 #include "revision.h" 10 10 #include "cache-tree.h" 11 - #include "path-list.h" 12 11 #include "unpack-trees.h" 13 12 #include "refs.h" 14 13 15 14 /* 16 15 * diff-files 17 16 */ 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 - /* 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 17 341 18 /* 342 19 * Has the work tree entity been removed?
+231
diff-no-index.c
··· 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 + }
+2 -4
diff.h
··· 250 250 /* report racily-clean paths as modified */ 251 251 #define DIFF_RACY_IS_MODIFIED 02 252 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 - 257 253 extern int run_diff_index(struct rev_info *revs, int cached); 258 254 259 255 extern int do_diff_cache(const unsigned char *, struct diff_options *); 260 256 extern int diff_flush_patch_id(struct diff_options *, unsigned char *); 261 257 262 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 *); 263 261 264 262 #endif /* DIFF_H */
+1
t/t4013-diff-various.sh
··· 257 257 diff --patch-with-stat -r initial..side 258 258 diff --patch-with-raw -r initial..side 259 259 diff --name-status dir2 dir 260 + diff --no-index --name-status dir2 dir 260 261 EOF 261 262 262 263 test_done
-1
t/t4013/diff.diff_--name-status_dir2_dir
··· 1 1 $ git diff --name-status dir2 dir 2 - A dir/sub 3 2 $
+3
t/t4013/diff.diff_--no-index_--name-status_dir2_dir
··· 1 + $ git diff --no-index --name-status dir2 dir 2 + A dir/sub 3 + $