diff options
Diffstat (limited to 'builtin/grep.c')
| -rw-r--r-- | builtin/grep.c | 107 | 
1 files changed, 58 insertions, 49 deletions
diff --git a/builtin/grep.c b/builtin/grep.c index d04f4400d9..ae738312aa 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -24,11 +24,11 @@ static char const * const grep_usage[] = {  	NULL  }; -static int use_threads = 1; +#define GREP_NUM_THREADS_DEFAULT 8 +static int num_threads;  #ifndef NO_PTHREADS -#define THREADS 8 -static pthread_t threads[THREADS]; +static pthread_t *threads;  /* We use one producer thread and THREADS consumer   * threads. The producer adds struct work_items to 'todo' and the @@ -63,13 +63,13 @@ static pthread_mutex_t grep_mutex;  static inline void grep_lock(void)  { -	if (use_threads) +	if (num_threads)  		pthread_mutex_lock(&grep_mutex);  }  static inline void grep_unlock(void)  { -	if (use_threads) +	if (num_threads)  		pthread_mutex_unlock(&grep_mutex);  } @@ -206,7 +206,8 @@ static void start_threads(struct grep_opt *opt)  		strbuf_init(&todo[i].out, 0);  	} -	for (i = 0; i < ARRAY_SIZE(threads); i++) { +	threads = xcalloc(num_threads, sizeof(*threads)); +	for (i = 0; i < num_threads; i++) {  		int err;  		struct grep_opt *o = grep_opt_dup(opt);  		o->output = strbuf_out; @@ -238,12 +239,14 @@ static int wait_all(void)  	pthread_cond_broadcast(&cond_add);  	grep_unlock(); -	for (i = 0; i < ARRAY_SIZE(threads); i++) { +	for (i = 0; i < num_threads; i++) {  		void *h;  		pthread_join(threads[i], &h);  		hit |= (int) (intptr_t) h;  	} +	free(threads); +  	pthread_mutex_destroy(&grep_mutex);  	pthread_mutex_destroy(&grep_read_mutex);  	pthread_mutex_destroy(&grep_attr_mutex); @@ -267,6 +270,14 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)  	int st = grep_config(var, value, cb);  	if (git_color_default_config(var, value, cb) < 0)  		st = -1; + +	if (!strcmp(var, "grep.threads")) { +		num_threads = git_config_int(var, value); +		if (num_threads < 0) +			die(_("invalid number of threads specified (%d) for %s"), +			    num_threads, var); +	} +  	return st;  } @@ -294,7 +305,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,  	}  #ifndef NO_PTHREADS -	if (use_threads) { +	if (num_threads) {  		add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);  		strbuf_release(&pathbuf);  		return 0; @@ -323,7 +334,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)  		strbuf_addstr(&buf, filename);  #ifndef NO_PTHREADS -	if (use_threads) { +	if (num_threads) {  		add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);  		strbuf_release(&buf);  		return 0; @@ -354,17 +365,17 @@ static void append_path(struct grep_opt *opt, const void *data, size_t len)  static void run_pager(struct grep_opt *opt, const char *prefix)  {  	struct string_list *path_list = opt->output_priv; -	const char **argv = xmalloc(sizeof(const char *) * (path_list->nr + 1)); +	struct child_process child = CHILD_PROCESS_INIT;  	int i, status;  	for (i = 0; i < path_list->nr; i++) -		argv[i] = path_list->items[i].string; -	argv[path_list->nr] = NULL; +		argv_array_push(&child.args, path_list->items[i].string); +	child.dir = prefix; +	child.use_shell = 1; -	status = run_command_v_opt_cd_env(argv, RUN_USING_SHELL, prefix, NULL); +	status = run_command(&child);  	if (status)  		exit(status); -	free(argv);  }  static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached) @@ -385,7 +396,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int  		 * cache version instead  		 */  		if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) { -			if (ce_stage(ce)) +			if (ce_stage(ce) || ce_intent_to_add(ce))  				continue;  			hit |= grep_sha1(opt, ce->sha1, ce->name, 0, ce->name);  		} @@ -427,7 +438,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,  		strbuf_add(base, entry.path, te_len);  		if (S_ISREG(entry.mode)) { -			hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len, +			hit |= grep_sha1(opt, entry.oid->hash, base->buf, tn_len,  					 check_attr ? base->buf + tn_len : NULL);  		}  		else if (S_ISDIR(entry.mode)) { @@ -436,10 +447,10 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,  			void *data;  			unsigned long size; -			data = lock_and_read_sha1_file(entry.sha1, &type, &size); +			data = lock_and_read_sha1_file(entry.oid->hash, &type, &size);  			if (!data)  				die(_("unable to read tree (%s)"), -				    sha1_to_hex(entry.sha1)); +				    oid_to_hex(entry.oid));  			strbuf_addch(base, '/');  			init_tree_desc(&sub, data, size); @@ -459,7 +470,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,  		       struct object *obj, const char *name, const char *path)  {  	if (obj->type == OBJ_BLOB) -		return grep_sha1(opt, obj->sha1, name, 0, path); +		return grep_sha1(opt, obj->oid.hash, name, 0, path);  	if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {  		struct tree_desc tree;  		void *data; @@ -468,12 +479,12 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,  		int hit, len;  		grep_read_lock(); -		data = read_object_with_reference(obj->sha1, tree_type, +		data = read_object_with_reference(obj->oid.hash, tree_type,  						  &size, NULL);  		grep_read_unlock();  		if (!data) -			die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1)); +			die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));  		len = name ? strlen(name) : 0;  		strbuf_init(&base, PATH_MAX + len + 1); @@ -511,12 +522,14 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,  }  static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec, -			  int exc_std) +			  int exc_std, int use_index)  {  	struct dir_struct dir;  	int i, hit = 0;  	memset(&dir, 0, sizeof(dir)); +	if (!use_index) +		dir.flags |= DIR_NO_GITLINKS;  	if (exc_std)  		setup_standard_excludes(&dir); @@ -562,7 +575,7 @@ static int file_callback(const struct option *opt, const char *arg, int unset)  	patterns = from_stdin ? stdin : fopen(arg, "r");  	if (!patterns)  		die_errno(_("cannot open '%s'"), arg); -	while (strbuf_getline(&sb, patterns, '\n') == 0) { +	while (strbuf_getline(&sb, patterns) == 0) {  		/* ignore empty line like grep does */  		if (sb.len == 0)  			continue; @@ -612,11 +625,6 @@ static int pattern_callback(const struct option *opt, const char *arg,  	return 0;  } -static int help_callback(const struct option *opt, const char *arg, int unset) -{ -	return -1; -} -  int cmd_grep(int argc, const char **argv, const char *prefix)  {  	int hit = 0; @@ -702,6 +710,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)  			N_("show <n> context lines before matches")),  		OPT_INTEGER('A', "after-context", &opt.post_context,  			N_("show <n> context lines after matches")), +		OPT_INTEGER(0, "threads", &num_threads, +			N_("use <n> worker threads")),  		OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),  			context_callback),  		OPT_BOOL('p', "show-function", &opt.funcname, @@ -738,18 +748,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)  			PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },  		OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,  			 N_("allow calling of grep(1) (ignored by this build)")), -		{ OPTION_CALLBACK, 0, "help-all", NULL, NULL, N_("show usage"), -		  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },  		OPT_END()  	}; -	/* -	 * 'git grep -h', unlike 'git grep -h <pattern>', is a request -	 * to show usage information and exit. -	 */ -	if (argc == 2 && !strcmp(argv[1], "-h")) -		usage_with_options(grep_usage, options); -  	init_grep_defaults();  	git_config(grep_cmd_config, NULL);  	grep_init(&opt, prefix); @@ -766,13 +767,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)  	 */  	argc = parse_options(argc, argv, prefix, options, grep_usage,  			     PARSE_OPT_KEEP_DASHDASH | -			     PARSE_OPT_STOP_AT_NON_OPTION | -			     PARSE_OPT_NO_INTERNAL_HELP); +			     PARSE_OPT_STOP_AT_NON_OPTION);  	grep_commit_pattern_type(pattern_type_arg, &opt); -	if (use_index && !startup_info->have_repository) -		/* die the same way as if we did it at the beginning */ -		setup_git_directory(); +	if (use_index && !startup_info->have_repository) { +		int fallback = 0; +		git_config_get_bool("grep.fallbacktonoindex", &fallback); +		if (fallback) +			use_index = 0; +		else +			/* die the same way as if we did it at the beginning */ +			setup_git_directory(); +	}  	/*  	 * skip a -- separator; we know it cannot be @@ -801,7 +807,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)  		opt.output_priv = &path_list;  		opt.output = append_path;  		string_list_append(&path_list, show_in_pager); -		use_threads = 0;  	}  	if (!opt.pattern_list) @@ -832,14 +837,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)  	}  #ifndef NO_PTHREADS -	if (list.nr || cached || online_cpus() == 1) -		use_threads = 0; +	if (list.nr || cached || show_in_pager) +		num_threads = 0; +	else if (num_threads == 0) +		num_threads = GREP_NUM_THREADS_DEFAULT; +	else if (num_threads < 0) +		die(_("invalid number of threads specified (%d)"), num_threads);  #else -	use_threads = 0; +	num_threads = 0;  #endif  #ifndef NO_PTHREADS -	if (use_threads) { +	if (num_threads) {  		if (!(opt.name_only || opt.unmatch_name_only || opt.count)  		    && (opt.pre_context || opt.post_context ||  			opt.file_break || opt.funcbody)) @@ -895,7 +904,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)  		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;  		if (list.nr)  			die(_("--no-index or --untracked cannot be used with revs.")); -		hit = grep_directory(&opt, &pathspec, use_exclude); +		hit = grep_directory(&opt, &pathspec, use_exclude, use_index);  	} else if (0 <= opt_exclude) {  		die(_("--[no-]exclude-standard cannot be used for tracked contents."));  	} else if (!list.nr) { @@ -909,7 +918,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)  		hit = grep_objects(&opt, &pathspec, &list);  	} -	if (use_threads) +	if (num_threads)  		hit |= wait_all();  	if (hit && show_in_pager)  		run_pager(&opt, prefix);  | 
