Merge branch 'jc/log-stdin'
* jc/log-stdin: Add trivial tests for --stdin option to log family Make --stdin option to "log" family read also pathspecs setup_revisions(): do not call get_pathspec() too early Teach --stdin option to "log" family read_revision_from_stdin(): use strbuf Conflicts: revision.cmaint
						commit
						e61f25f3a6
					
				|  | @ -243,12 +243,14 @@ endif::git-rev-list[] | ||||||
| 	Pretend as if all the refs in `$GIT_DIR/refs/remotes` are listed | 	Pretend as if all the refs in `$GIT_DIR/refs/remotes` are listed | ||||||
| 	on the command line as '<commit>'. | 	on the command line as '<commit>'. | ||||||
|  |  | ||||||
| ifdef::git-rev-list[] |  | ||||||
| --stdin:: | --stdin:: | ||||||
|  |  | ||||||
| 	In addition to the '<commit>' listed on the command | 	In addition to the '<commit>' listed on the command | ||||||
| 	line, read them from the standard input. | 	line, read them from the standard input. If a '--' separator is | ||||||
|  | 	seen, stop reading commits and start reading paths to limit the | ||||||
|  | 	result. | ||||||
|  |  | ||||||
|  | ifdef::git-rev-list[] | ||||||
| --quiet:: | --quiet:: | ||||||
|  |  | ||||||
| 	Don't print anything to standard output.  This form | 	Don't print anything to standard output.  This form | ||||||
|  |  | ||||||
|  | @ -2358,6 +2358,7 @@ parse_done: | ||||||
| 			die_errno("cannot stat path '%s'", path); | 			die_errno("cannot stat path '%s'", path); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	revs.disable_stdin = 1; | ||||||
| 	setup_revisions(argc, argv, &revs, NULL); | 	setup_revisions(argc, argv, &revs, NULL); | ||||||
| 	memset(&sb, 0, sizeof(sb)); | 	memset(&sb, 0, sizeof(sb)); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -104,6 +104,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) | ||||||
| 	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ | 	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ | ||||||
| 	opt->abbrev = 0; | 	opt->abbrev = 0; | ||||||
| 	opt->diff = 1; | 	opt->diff = 1; | ||||||
|  | 	opt->disable_stdin = 1; | ||||||
| 	argc = setup_revisions(argc, argv, opt, NULL); | 	argc = setup_revisions(argc, argv, opt, NULL); | ||||||
|  |  | ||||||
| 	while (--argc > 0) { | 	while (--argc > 0) { | ||||||
|  |  | ||||||
|  | @ -306,7 +306,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) | ||||||
| 	struct rev_info revs; | 	struct rev_info revs; | ||||||
| 	struct rev_list_info info; | 	struct rev_list_info info; | ||||||
| 	int i; | 	int i; | ||||||
| 	int read_from_stdin = 0; |  | ||||||
| 	int bisect_list = 0; | 	int bisect_list = 0; | ||||||
| 	int bisect_show_vars = 0; | 	int bisect_show_vars = 0; | ||||||
| 	int bisect_find_all = 0; | 	int bisect_find_all = 0; | ||||||
|  | @ -351,12 +350,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) | ||||||
| 			bisect_show_vars = 1; | 			bisect_show_vars = 1; | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		if (!strcmp(arg, "--stdin")) { |  | ||||||
| 			if (read_from_stdin++) |  | ||||||
| 				die("--stdin given twice?"); |  | ||||||
| 			read_revisions_from_stdin(&revs); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 		usage(rev_list_usage); | 		usage(rev_list_usage); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								bundle.c
								
								
								
								
							
							
						
						
									
										12
									
								
								bundle.c
								
								
								
								
							|  | @ -204,7 +204,6 @@ int create_bundle(struct bundle_header *header, const char *path, | ||||||
| 	int i, ref_count = 0; | 	int i, ref_count = 0; | ||||||
| 	char buffer[1024]; | 	char buffer[1024]; | ||||||
| 	struct rev_info revs; | 	struct rev_info revs; | ||||||
| 	int read_from_stdin = 0; |  | ||||||
| 	struct child_process rls; | 	struct child_process rls; | ||||||
| 	FILE *rls_fout; | 	FILE *rls_fout; | ||||||
|  |  | ||||||
|  | @ -256,15 +255,8 @@ int create_bundle(struct bundle_header *header, const char *path, | ||||||
| 	/* write references */ | 	/* write references */ | ||||||
| 	argc = setup_revisions(argc, argv, &revs, NULL); | 	argc = setup_revisions(argc, argv, &revs, NULL); | ||||||
|  |  | ||||||
| 	for (i = 1; i < argc; i++) { | 	if (argc > 1) | ||||||
| 		if (!strcmp(argv[i], "--stdin")) { | 		return error("unrecognized argument: %s'", argv[1]); | ||||||
| 			if (read_from_stdin++) |  | ||||||
| 				die("--stdin given twice?"); |  | ||||||
| 			read_revisions_from_stdin(&revs); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 		return error("unrecognized argument: %s'", argv[i]); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	object_array_remove_duplicates(&revs.pending); | 	object_array_remove_duplicates(&revs.pending); | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										108
									
								
								revision.c
								
								
								
								
							
							
						
						
									
										108
									
								
								revision.c
								
								
								
								
							|  | @ -953,21 +953,59 @@ int handle_revision_arg(const char *arg, struct rev_info *revs, | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void read_revisions_from_stdin(struct rev_info *revs) | static void read_pathspec_from_stdin(struct rev_info *revs, struct strbuf *sb, const char ***prune_data) | ||||||
| { | { | ||||||
| 	char line[1000]; | 	const char **prune = *prune_data; | ||||||
|  | 	int prune_nr; | ||||||
|  | 	int prune_alloc; | ||||||
|  |  | ||||||
| 	while (fgets(line, sizeof(line), stdin) != NULL) { | 	/* count existing ones */ | ||||||
| 		int len = strlen(line); | 	if (!prune) | ||||||
| 		if (len && line[len - 1] == '\n') | 		prune_nr = 0; | ||||||
| 			line[--len] = '\0'; | 	else | ||||||
|  | 		for (prune_nr = 0; prune[prune_nr]; prune_nr++) | ||||||
|  | 			; | ||||||
|  | 	prune_alloc = prune_nr; /* not really, but we do not know */ | ||||||
|  |  | ||||||
|  | 	while (strbuf_getwholeline(sb, stdin, '\n') != EOF) { | ||||||
|  | 		int len = sb->len; | ||||||
|  | 		if (len && sb->buf[len - 1] == '\n') | ||||||
|  | 			sb->buf[--len] = '\0'; | ||||||
|  | 		ALLOC_GROW(prune, prune_nr+1, prune_alloc); | ||||||
|  | 		prune[prune_nr++] = xstrdup(sb->buf); | ||||||
|  | 	} | ||||||
|  | 	if (prune) { | ||||||
|  | 		ALLOC_GROW(prune, prune_nr+1, prune_alloc); | ||||||
|  | 		prune[prune_nr] = NULL; | ||||||
|  | 	} | ||||||
|  | 	*prune_data = prune; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void read_revisions_from_stdin(struct rev_info *revs, const char ***prune) | ||||||
|  | { | ||||||
|  | 	struct strbuf sb; | ||||||
|  | 	int seen_dashdash = 0; | ||||||
|  |  | ||||||
|  | 	strbuf_init(&sb, 1000); | ||||||
|  | 	while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) { | ||||||
|  | 		int len = sb.len; | ||||||
|  | 		if (len && sb.buf[len - 1] == '\n') | ||||||
|  | 			sb.buf[--len] = '\0'; | ||||||
| 		if (!len) | 		if (!len) | ||||||
| 			break; | 			break; | ||||||
| 		if (line[0] == '-') | 		if (sb.buf[0] == '-') { | ||||||
| 			die("options not supported in --stdin mode"); | 			if (len == 2 && sb.buf[1] == '-') { | ||||||
| 		if (handle_revision_arg(line, revs, 0, 1)) | 				seen_dashdash = 1; | ||||||
| 			die("bad revision '%s'", line); | 				break; | ||||||
| 			} | 			} | ||||||
|  | 			die("options not supported in --stdin mode"); | ||||||
|  | 		} | ||||||
|  | 		if (handle_revision_arg(sb.buf, revs, 0, 1)) | ||||||
|  | 			die("bad revision '%s'", sb.buf); | ||||||
|  | 	} | ||||||
|  | 	if (seen_dashdash) | ||||||
|  | 		read_pathspec_from_stdin(revs, &sb, prune); | ||||||
|  | 	strbuf_release(&sb); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what) | static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what) | ||||||
|  | @ -1229,6 +1267,34 @@ static int for_each_good_bisect_ref(each_ref_fn fn, void *cb_data) | ||||||
| 	return for_each_ref_in("refs/bisect/good", fn, cb_data); | 	return for_each_ref_in("refs/bisect/good", fn, cb_data); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void append_prune_data(const char ***prune_data, const char **av) | ||||||
|  | { | ||||||
|  | 	const char **prune = *prune_data; | ||||||
|  | 	int prune_nr; | ||||||
|  | 	int prune_alloc; | ||||||
|  |  | ||||||
|  | 	if (!prune) { | ||||||
|  | 		*prune_data = av; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* count existing ones */ | ||||||
|  | 	for (prune_nr = 0; prune[prune_nr]; prune_nr++) | ||||||
|  | 		; | ||||||
|  | 	prune_alloc = prune_nr; /* not really, but we do not know */ | ||||||
|  |  | ||||||
|  | 	while (*av) { | ||||||
|  | 		ALLOC_GROW(prune, prune_nr+1, prune_alloc); | ||||||
|  | 		prune[prune_nr++] = *av; | ||||||
|  | 		av++; | ||||||
|  | 	} | ||||||
|  | 	if (prune) { | ||||||
|  | 		ALLOC_GROW(prune, prune_nr+1, prune_alloc); | ||||||
|  | 		prune[prune_nr] = NULL; | ||||||
|  | 	} | ||||||
|  | 	*prune_data = prune; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Parse revision information, filling in the "rev_info" structure, |  * Parse revision information, filling in the "rev_info" structure, | ||||||
|  * and removing the used arguments from the argument list. |  * and removing the used arguments from the argument list. | ||||||
|  | @ -1238,7 +1304,8 @@ static int for_each_good_bisect_ref(each_ref_fn fn, void *cb_data) | ||||||
|  */ |  */ | ||||||
| int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def) | int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def) | ||||||
| { | { | ||||||
| 	int i, flags, left, seen_dashdash; | 	int i, flags, left, seen_dashdash, read_from_stdin; | ||||||
|  | 	const char **prune_data = NULL; | ||||||
|  |  | ||||||
| 	/* First, search for "--" */ | 	/* First, search for "--" */ | ||||||
| 	seen_dashdash = 0; | 	seen_dashdash = 0; | ||||||
|  | @ -1249,13 +1316,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch | ||||||
| 		argv[i] = NULL; | 		argv[i] = NULL; | ||||||
| 		argc = i; | 		argc = i; | ||||||
| 		if (argv[i + 1]) | 		if (argv[i + 1]) | ||||||
| 			revs->prune_data = get_pathspec(revs->prefix, argv + i + 1); | 			prune_data = argv + i + 1; | ||||||
| 		seen_dashdash = 1; | 		seen_dashdash = 1; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Second, deal with arguments and options */ | 	/* Second, deal with arguments and options */ | ||||||
| 	flags = 0; | 	flags = 0; | ||||||
|  | 	read_from_stdin = 0; | ||||||
| 	for (left = i = 1; i < argc; i++) { | 	for (left = i = 1; i < argc; i++) { | ||||||
| 		const char *arg = argv[i]; | 		const char *arg = argv[i]; | ||||||
| 		if (*arg == '-') { | 		if (*arg == '-') { | ||||||
|  | @ -1300,6 +1368,16 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch | ||||||
| 				revs->no_walk = 0; | 				revs->no_walk = 0; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (!strcmp(arg, "--stdin")) { | ||||||
|  | 				if (revs->disable_stdin) { | ||||||
|  | 					argv[left++] = arg; | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				if (read_from_stdin++) | ||||||
|  | 					die("--stdin given twice?"); | ||||||
|  | 				read_revisions_from_stdin(revs, &prune_data); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			opts = handle_revision_opt(revs, argc - i, argv + i, &left, argv); | 			opts = handle_revision_opt(revs, argc - i, argv + i, &left, argv); | ||||||
| 			if (opts > 0) { | 			if (opts > 0) { | ||||||
|  | @ -1325,12 +1403,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch | ||||||
| 			for (j = i; j < argc; j++) | 			for (j = i; j < argc; j++) | ||||||
| 				verify_filename(revs->prefix, argv[j]); | 				verify_filename(revs->prefix, argv[j]); | ||||||
|  |  | ||||||
| 			revs->prune_data = get_pathspec(revs->prefix, | 			append_prune_data(&prune_data, argv + i); | ||||||
| 							argv + i); |  | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (prune_data) | ||||||
|  | 		revs->prune_data = get_pathspec(revs->prefix, prune_data); | ||||||
|  |  | ||||||
| 	if (revs->def == NULL) | 	if (revs->def == NULL) | ||||||
| 		revs->def = def; | 		revs->def = def; | ||||||
| 	if (revs->show_merge) | 	if (revs->show_merge) | ||||||
|  |  | ||||||
|  | @ -84,6 +84,8 @@ struct rev_info { | ||||||
| 			use_terminator:1, | 			use_terminator:1, | ||||||
| 			missing_newline:1, | 			missing_newline:1, | ||||||
| 			date_mode_explicit:1; | 			date_mode_explicit:1; | ||||||
|  | 	unsigned int	disable_stdin:1; | ||||||
|  |  | ||||||
| 	enum date_mode date_mode; | 	enum date_mode date_mode; | ||||||
|  |  | ||||||
| 	unsigned int	abbrev; | 	unsigned int	abbrev; | ||||||
|  | @ -129,8 +131,6 @@ struct rev_info { | ||||||
| #define REV_TREE_DIFFERENT	3	/* Mixed changes */ | #define REV_TREE_DIFFERENT	3	/* Mixed changes */ | ||||||
|  |  | ||||||
| /* revision.c */ | /* revision.c */ | ||||||
| void read_revisions_from_stdin(struct rev_info *revs); |  | ||||||
|  |  | ||||||
| typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *); | typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *); | ||||||
| extern volatile show_early_output_fn_t show_early_output; | extern volatile show_early_output_fn_t show_early_output; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -0,0 +1,61 @@ | ||||||
|  | #!/bin/sh | ||||||
|  | # | ||||||
|  | # Copyright (c) 2009, Junio C Hamano | ||||||
|  | # | ||||||
|  |  | ||||||
|  | test_description='log family learns --stdin' | ||||||
|  |  | ||||||
|  | . ./test-lib.sh | ||||||
|  |  | ||||||
|  | check () { | ||||||
|  | 	for cmd in rev-list "log --stat" | ||||||
|  | 	do | ||||||
|  | 		for i in "$@" | ||||||
|  | 		do | ||||||
|  | 			printf "%s\n" $i | ||||||
|  | 		done >input && | ||||||
|  | 		test_expect_success "check $cmd $*" ' | ||||||
|  | 			git $cmd $(cat input) >expect && | ||||||
|  | 			git $cmd --stdin <input >actual && | ||||||
|  | 			sed -e "s/^/input /" input && | ||||||
|  | 			sed -e "s/^/output /" expect && | ||||||
|  | 			test_cmp expect actual | ||||||
|  | 		' | ||||||
|  | 	done | ||||||
|  | } | ||||||
|  |  | ||||||
|  | them='1 2 3 4 5 6 7' | ||||||
|  |  | ||||||
|  | test_expect_success setup ' | ||||||
|  | 	( | ||||||
|  | 		for i in 0 $them | ||||||
|  | 		do | ||||||
|  | 			for j in $them | ||||||
|  | 			do | ||||||
|  | 				echo $i.$j >file-$j && | ||||||
|  | 				git add file-$j || exit | ||||||
|  | 			done && | ||||||
|  | 			test_tick && | ||||||
|  | 			git commit -m $i || exit | ||||||
|  | 		done && | ||||||
|  | 		for i in $them | ||||||
|  | 		do | ||||||
|  | 			git checkout -b side-$i master~$i && | ||||||
|  | 			echo updated $i >file-$i && | ||||||
|  | 			git add file-$i && | ||||||
|  | 			test_tick && | ||||||
|  | 			git commit -m side-$i || exit | ||||||
|  | 		done | ||||||
|  | 	) | ||||||
|  | ' | ||||||
|  |  | ||||||
|  | check master | ||||||
|  | check side-1 ^side-4 | ||||||
|  | check side-1 ^side-7 -- | ||||||
|  | check side-1 ^side-7 -- file-1 | ||||||
|  | check side-1 ^side-7 -- file-2 | ||||||
|  | check side-3 ^side-4 -- file-3 | ||||||
|  | check side-3 ^side-2 | ||||||
|  | check side-3 ^side-2 -- file-1 | ||||||
|  |  | ||||||
|  | test_done | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano