diff-index.c: "git diff" has no need to read blob from the standard input
Only "diff --no-index -" does. Bolting the logic into the low-level function diff_populate_filespec() was a layering violation from day one. Move populate_from_stdin() function out of the generic diff.c to its only user, diff-index.c. Also make sure "-" from the command line stays a special token "read from the standard input", even if we later decide to sanitize the result from prefix_filename() function in a few obvious ways, e.g. removing unnecessary "./" prefix, duplicated slashes "//" in the middle, etc. Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									3b069b1beb
								
							
						
					
					
						commit
						4682d8521c
					
				|  | @ -32,6 +32,13 @@ static int read_directory(const char *path, struct string_list *list) | |||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * This should be "(standard input)" or something, but it will | ||||
|  * probably expose many more breakages in the way no-index code | ||||
|  * is bolted onto the diff callchain. | ||||
|  */ | ||||
| static const char file_from_standard_input[] = "-"; | ||||
|  | ||||
| static int get_mode(const char *path, int *mode) | ||||
| { | ||||
| 	struct stat st; | ||||
|  | @ -42,7 +49,7 @@ static int get_mode(const char *path, int *mode) | |||
| 	else if (!strcasecmp(path, "nul")) | ||||
| 		*mode = 0; | ||||
| #endif | ||||
| 	else if (!strcmp(path, "-")) | ||||
| 	else if (path == file_from_standard_input) | ||||
| 		*mode = create_ce_mode(0666); | ||||
| 	else if (lstat(path, &st)) | ||||
| 		return error("Could not access '%s'", path); | ||||
|  | @ -51,6 +58,36 @@ static int get_mode(const char *path, int *mode) | |||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int populate_from_stdin(struct diff_filespec *s) | ||||
| { | ||||
| 	struct strbuf buf = STRBUF_INIT; | ||||
| 	size_t size = 0; | ||||
|  | ||||
| 	if (strbuf_read(&buf, 0, 0) < 0) | ||||
| 		return error("error while reading from stdin %s", | ||||
| 				     strerror(errno)); | ||||
|  | ||||
| 	s->should_munmap = 0; | ||||
| 	s->data = strbuf_detach(&buf, &size); | ||||
| 	s->size = size; | ||||
| 	s->should_free = 1; | ||||
| 	s->is_stdin = 1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct diff_filespec *noindex_filespec(const char *name, int mode) | ||||
| { | ||||
| 	struct diff_filespec *s; | ||||
|  | ||||
| 	if (!name) | ||||
| 		name = "/dev/null"; | ||||
| 	s = alloc_filespec(name); | ||||
| 	fill_filespec(s, null_sha1, mode); | ||||
| 	if (name == file_from_standard_input) | ||||
| 		populate_from_stdin(s); | ||||
| 	return s; | ||||
| } | ||||
|  | ||||
| static int queue_diff(struct diff_options *o, | ||||
| 		const char *name1, const char *name2) | ||||
| { | ||||
|  | @ -135,15 +172,8 @@ static int queue_diff(struct diff_options *o, | |||
| 			tmp_c = name1; name1 = name2; name2 = tmp_c; | ||||
| 		} | ||||
|  | ||||
| 		if (!name1) | ||||
| 			name1 = "/dev/null"; | ||||
| 		if (!name2) | ||||
| 			name2 = "/dev/null"; | ||||
| 		d1 = alloc_filespec(name1); | ||||
| 		d2 = alloc_filespec(name2); | ||||
| 		fill_filespec(d1, null_sha1, mode1); | ||||
| 		fill_filespec(d2, null_sha1, mode2); | ||||
|  | ||||
| 		d1 = noindex_filespec(name1, mode1); | ||||
| 		d2 = noindex_filespec(name2, mode2); | ||||
| 		diff_queue(&diff_queued_diff, d1, d2); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | @ -238,7 +268,7 @@ void diff_no_index(struct rev_info *revs, | |||
| 			 * stdin should be spelled as "-"; if you have | ||||
| 			 * path that is "-", spell it as "./-". | ||||
| 			 */ | ||||
| 			p = p; | ||||
| 			p = file_from_standard_input; | ||||
| 		else if (prefixlen) | ||||
| 			p = xstrdup(prefix_filename(prefix, prefixlen, p)); | ||||
| 		paths[i] = p; | ||||
|  |  | |||
							
								
								
									
										21
									
								
								diff.c
								
								
								
								
							
							
						
						
									
										21
									
								
								diff.c
								
								
								
								
							|  | @ -2426,22 +2426,6 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int | |||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int populate_from_stdin(struct diff_filespec *s) | ||||
| { | ||||
| 	struct strbuf buf = STRBUF_INIT; | ||||
| 	size_t size = 0; | ||||
|  | ||||
| 	if (strbuf_read(&buf, 0, 0) < 0) | ||||
| 		return error("error while reading from stdin %s", | ||||
| 				     strerror(errno)); | ||||
|  | ||||
| 	s->should_munmap = 0; | ||||
| 	s->data = strbuf_detach(&buf, &size); | ||||
| 	s->size = size; | ||||
| 	s->should_free = 1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int diff_populate_gitlink(struct diff_filespec *s, int size_only) | ||||
| { | ||||
| 	int len; | ||||
|  | @ -2491,9 +2475,6 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) | |||
| 		struct stat st; | ||||
| 		int fd; | ||||
|  | ||||
| 		if (!strcmp(s->path, "-")) | ||||
| 			return populate_from_stdin(s); | ||||
|  | ||||
| 		if (lstat(s->path, &st) < 0) { | ||||
| 			if (errno == ENOENT) { | ||||
| 			err_empty: | ||||
|  | @ -2855,7 +2836,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one) | |||
| 	if (DIFF_FILE_VALID(one)) { | ||||
| 		if (!one->sha1_valid) { | ||||
| 			struct stat st; | ||||
| 			if (!strcmp(one->path, "-")) { | ||||
| 			if (one->is_stdin) { | ||||
| 				hashcpy(one->sha1, null_sha1); | ||||
| 				return; | ||||
| 			} | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ struct diff_filespec { | |||
| 	unsigned should_free : 1; /* data should be free()'ed */ | ||||
| 	unsigned should_munmap : 1; /* data should be munmap()'ed */ | ||||
| 	unsigned dirty_submodule : 2;  /* For submodules: its work tree is dirty */ | ||||
| 	unsigned is_stdin : 1; | ||||
| #define DIRTY_SUBMODULE_UNTRACKED 1 | ||||
| #define DIRTY_SUBMODULE_MODIFIED  2 | ||||
|  | ||||
|  |  | |||
|  | @ -458,4 +458,16 @@ test_expect_success 'amend can copy notes' ' | |||
|  | ||||
| ' | ||||
|  | ||||
| test_expect_success 'commit a file whose name is a dash' ' | ||||
| 	git reset --hard && | ||||
| 	for i in 1 2 3 4 5 | ||||
| 	do | ||||
| 		echo $i | ||||
| 	done >./- && | ||||
| 	git add ./- && | ||||
| 	test_tick && | ||||
| 	git commit -m "add dash" >output </dev/null && | ||||
| 	test_i18ngrep " changed, 5 insertions" output | ||||
| ' | ||||
|  | ||||
| test_done | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano