grep: recurse in-process using 'struct repository'
Convert grep to use 'struct repository' which enables recursing into submodules to be handled in-process. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									2184d4ba0c
								
							
						
					
					
						commit
						f9ee2fcdfa
					
				|  | @ -95,13 +95,6 @@ OPTIONS | ||||||
| 	<tree> option the prefix of all submodule output will be the name of | 	<tree> option the prefix of all submodule output will be the name of | ||||||
| 	the parent project's <tree> object. | 	the parent project's <tree> object. | ||||||
|  |  | ||||||
| --parent-basename <basename>:: |  | ||||||
| 	For internal use only.  In order to produce uniform output with the |  | ||||||
| 	--recurse-submodules option, this option can be used to provide the |  | ||||||
| 	basename of a parent's <tree> object to a submodule so the submodule |  | ||||||
| 	can prefix its output with the parent's name rather than the SHA1 of |  | ||||||
| 	the submodule. |  | ||||||
|  |  | ||||||
| -a:: | -a:: | ||||||
| --text:: | --text:: | ||||||
| 	Process binary files as if they were text. | 	Process binary files as if they were text. | ||||||
|  |  | ||||||
							
								
								
									
										416
									
								
								builtin/grep.c
								
								
								
								
							
							
						
						
									
										416
									
								
								builtin/grep.c
								
								
								
								
							|  | @ -28,13 +28,7 @@ static char const * const grep_usage[] = { | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static const char *super_prefix; |  | ||||||
| static int recurse_submodules; | static int recurse_submodules; | ||||||
| static struct argv_array submodule_options = ARGV_ARRAY_INIT; |  | ||||||
| static const char *parent_basename; |  | ||||||
|  |  | ||||||
| static int grep_submodule_launch(struct grep_opt *opt, |  | ||||||
| 				 const struct grep_source *gs); |  | ||||||
|  |  | ||||||
| #define GREP_NUM_THREADS_DEFAULT 8 | #define GREP_NUM_THREADS_DEFAULT 8 | ||||||
| static int num_threads; | static int num_threads; | ||||||
|  | @ -186,10 +180,7 @@ static void *run(void *arg) | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		opt->output_priv = w; | 		opt->output_priv = w; | ||||||
| 		if (w->source.type == GREP_SOURCE_SUBMODULE) | 		hit |= grep_source(opt, &w->source); | ||||||
| 			hit |= grep_submodule_launch(opt, &w->source); |  | ||||||
| 		else |  | ||||||
| 			hit |= grep_source(opt, &w->source); |  | ||||||
| 		grep_source_clear_data(&w->source); | 		grep_source_clear_data(&w->source); | ||||||
| 		work_done(w); | 		work_done(w); | ||||||
| 	} | 	} | ||||||
|  | @ -327,21 +318,13 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid, | ||||||
| { | { | ||||||
| 	struct strbuf pathbuf = STRBUF_INIT; | 	struct strbuf pathbuf = STRBUF_INIT; | ||||||
|  |  | ||||||
| 	if (super_prefix) { | 	if (opt->relative && opt->prefix_length) { | ||||||
| 		strbuf_add(&pathbuf, filename, tree_name_len); | 		quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf); | ||||||
| 		strbuf_addstr(&pathbuf, super_prefix); | 		strbuf_insert(&pathbuf, 0, filename, tree_name_len); | ||||||
| 		strbuf_addstr(&pathbuf, filename + tree_name_len); |  | ||||||
| 	} else { | 	} else { | ||||||
| 		strbuf_addstr(&pathbuf, filename); | 		strbuf_addstr(&pathbuf, filename); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (opt->relative && opt->prefix_length) { |  | ||||||
| 		char *name = strbuf_detach(&pathbuf, NULL); |  | ||||||
| 		quote_path_relative(name + tree_name_len, opt->prefix, &pathbuf); |  | ||||||
| 		strbuf_insert(&pathbuf, 0, name, tree_name_len); |  | ||||||
| 		free(name); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| #ifndef NO_PTHREADS | #ifndef NO_PTHREADS | ||||||
| 	if (num_threads) { | 	if (num_threads) { | ||||||
| 		add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid); | 		add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid); | ||||||
|  | @ -366,15 +349,10 @@ static int grep_file(struct grep_opt *opt, const char *filename) | ||||||
| { | { | ||||||
| 	struct strbuf buf = STRBUF_INIT; | 	struct strbuf buf = STRBUF_INIT; | ||||||
|  |  | ||||||
| 	if (super_prefix) | 	if (opt->relative && opt->prefix_length) | ||||||
| 		strbuf_addstr(&buf, super_prefix); | 		quote_path_relative(filename, opt->prefix, &buf); | ||||||
| 	strbuf_addstr(&buf, filename); | 	else | ||||||
|  | 		strbuf_addstr(&buf, filename); | ||||||
| 	if (opt->relative && opt->prefix_length) { |  | ||||||
| 		char *name = strbuf_detach(&buf, NULL); |  | ||||||
| 		quote_path_relative(name, opt->prefix, &buf); |  | ||||||
| 		free(name); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| #ifndef NO_PTHREADS | #ifndef NO_PTHREADS | ||||||
| 	if (num_threads) { | 	if (num_threads) { | ||||||
|  | @ -421,284 +399,89 @@ static void run_pager(struct grep_opt *opt, const char *prefix) | ||||||
| 		exit(status); | 		exit(status); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void compile_submodule_options(const struct grep_opt *opt, | static int grep_cache(struct grep_opt *opt, struct repository *repo, | ||||||
| 				      const char **argv, | 		      const struct pathspec *pathspec, int cached); | ||||||
| 				      int cached, int untracked, | static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 				      int opt_exclude, int use_index, | 		     struct tree_desc *tree, struct strbuf *base, int tn_len, | ||||||
| 				      int pattern_type_arg) | 		     int check_attr, struct repository *repo); | ||||||
| { |  | ||||||
| 	struct grep_pat *pattern; |  | ||||||
|  |  | ||||||
| 	if (recurse_submodules) | static int grep_submodule(struct grep_opt *opt, struct repository *superproject, | ||||||
| 		argv_array_push(&submodule_options, "--recurse-submodules"); | 			  const struct pathspec *pathspec, | ||||||
|  | 			  const struct object_id *oid, | ||||||
| 	if (cached) |  | ||||||
| 		argv_array_push(&submodule_options, "--cached"); |  | ||||||
| 	if (!use_index) |  | ||||||
| 		argv_array_push(&submodule_options, "--no-index"); |  | ||||||
| 	if (untracked) |  | ||||||
| 		argv_array_push(&submodule_options, "--untracked"); |  | ||||||
| 	if (opt_exclude > 0) |  | ||||||
| 		argv_array_push(&submodule_options, "--exclude-standard"); |  | ||||||
|  |  | ||||||
| 	if (opt->invert) |  | ||||||
| 		argv_array_push(&submodule_options, "-v"); |  | ||||||
| 	if (opt->ignore_case) |  | ||||||
| 		argv_array_push(&submodule_options, "-i"); |  | ||||||
| 	if (opt->word_regexp) |  | ||||||
| 		argv_array_push(&submodule_options, "-w"); |  | ||||||
| 	switch (opt->binary) { |  | ||||||
| 	case GREP_BINARY_NOMATCH: |  | ||||||
| 		argv_array_push(&submodule_options, "-I"); |  | ||||||
| 		break; |  | ||||||
| 	case GREP_BINARY_TEXT: |  | ||||||
| 		argv_array_push(&submodule_options, "-a"); |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 	if (opt->allow_textconv) |  | ||||||
| 		argv_array_push(&submodule_options, "--textconv"); |  | ||||||
| 	if (opt->max_depth != -1) |  | ||||||
| 		argv_array_pushf(&submodule_options, "--max-depth=%d", |  | ||||||
| 				 opt->max_depth); |  | ||||||
| 	if (opt->linenum) |  | ||||||
| 		argv_array_push(&submodule_options, "-n"); |  | ||||||
| 	if (!opt->pathname) |  | ||||||
| 		argv_array_push(&submodule_options, "-h"); |  | ||||||
| 	if (!opt->relative) |  | ||||||
| 		argv_array_push(&submodule_options, "--full-name"); |  | ||||||
| 	if (opt->name_only) |  | ||||||
| 		argv_array_push(&submodule_options, "-l"); |  | ||||||
| 	if (opt->unmatch_name_only) |  | ||||||
| 		argv_array_push(&submodule_options, "-L"); |  | ||||||
| 	if (opt->null_following_name) |  | ||||||
| 		argv_array_push(&submodule_options, "-z"); |  | ||||||
| 	if (opt->count) |  | ||||||
| 		argv_array_push(&submodule_options, "-c"); |  | ||||||
| 	if (opt->file_break) |  | ||||||
| 		argv_array_push(&submodule_options, "--break"); |  | ||||||
| 	if (opt->heading) |  | ||||||
| 		argv_array_push(&submodule_options, "--heading"); |  | ||||||
| 	if (opt->pre_context) |  | ||||||
| 		argv_array_pushf(&submodule_options, "--before-context=%d", |  | ||||||
| 				 opt->pre_context); |  | ||||||
| 	if (opt->post_context) |  | ||||||
| 		argv_array_pushf(&submodule_options, "--after-context=%d", |  | ||||||
| 				 opt->post_context); |  | ||||||
| 	if (opt->funcname) |  | ||||||
| 		argv_array_push(&submodule_options, "-p"); |  | ||||||
| 	if (opt->funcbody) |  | ||||||
| 		argv_array_push(&submodule_options, "-W"); |  | ||||||
| 	if (opt->all_match) |  | ||||||
| 		argv_array_push(&submodule_options, "--all-match"); |  | ||||||
| 	if (opt->debug) |  | ||||||
| 		argv_array_push(&submodule_options, "--debug"); |  | ||||||
| 	if (opt->status_only) |  | ||||||
| 		argv_array_push(&submodule_options, "-q"); |  | ||||||
|  |  | ||||||
| 	switch (pattern_type_arg) { |  | ||||||
| 	case GREP_PATTERN_TYPE_BRE: |  | ||||||
| 		argv_array_push(&submodule_options, "-G"); |  | ||||||
| 		break; |  | ||||||
| 	case GREP_PATTERN_TYPE_ERE: |  | ||||||
| 		argv_array_push(&submodule_options, "-E"); |  | ||||||
| 		break; |  | ||||||
| 	case GREP_PATTERN_TYPE_FIXED: |  | ||||||
| 		argv_array_push(&submodule_options, "-F"); |  | ||||||
| 		break; |  | ||||||
| 	case GREP_PATTERN_TYPE_PCRE: |  | ||||||
| 		argv_array_push(&submodule_options, "-P"); |  | ||||||
| 		break; |  | ||||||
| 	case GREP_PATTERN_TYPE_UNSPECIFIED: |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		die("BUG: Added a new grep pattern type without updating switch statement"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for (pattern = opt->pattern_list; pattern != NULL; |  | ||||||
| 	     pattern = pattern->next) { |  | ||||||
| 		switch (pattern->token) { |  | ||||||
| 		case GREP_PATTERN: |  | ||||||
| 			argv_array_pushf(&submodule_options, "-e%s", |  | ||||||
| 					 pattern->pattern); |  | ||||||
| 			break; |  | ||||||
| 		case GREP_AND: |  | ||||||
| 		case GREP_OPEN_PAREN: |  | ||||||
| 		case GREP_CLOSE_PAREN: |  | ||||||
| 		case GREP_NOT: |  | ||||||
| 		case GREP_OR: |  | ||||||
| 			argv_array_push(&submodule_options, pattern->pattern); |  | ||||||
| 			break; |  | ||||||
| 		/* BODY and HEAD are not used by git-grep */ |  | ||||||
| 		case GREP_PATTERN_BODY: |  | ||||||
| 		case GREP_PATTERN_HEAD: |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Limit number of threads for child process to use. |  | ||||||
| 	 * This is to prevent potential fork-bomb behavior of git-grep as each |  | ||||||
| 	 * submodule process has its own thread pool. |  | ||||||
| 	 */ |  | ||||||
| 	argv_array_pushf(&submodule_options, "--threads=%d", |  | ||||||
| 			 DIV_ROUND_UP(num_threads, 2)); |  | ||||||
|  |  | ||||||
| 	/* Add Pathspecs */ |  | ||||||
| 	argv_array_push(&submodule_options, "--"); |  | ||||||
| 	for (; *argv; argv++) |  | ||||||
| 		argv_array_push(&submodule_options, *argv); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Launch child process to grep contents of a submodule |  | ||||||
|  */ |  | ||||||
| static int grep_submodule_launch(struct grep_opt *opt, |  | ||||||
| 				 const struct grep_source *gs) |  | ||||||
| { |  | ||||||
| 	struct child_process cp = CHILD_PROCESS_INIT; |  | ||||||
| 	int status, i; |  | ||||||
| 	const char *end_of_base; |  | ||||||
| 	const char *name; |  | ||||||
| 	struct strbuf child_output = STRBUF_INIT; |  | ||||||
|  |  | ||||||
| 	end_of_base = strchr(gs->name, ':'); |  | ||||||
| 	if (gs->identifier && end_of_base) |  | ||||||
| 		name = end_of_base + 1; |  | ||||||
| 	else |  | ||||||
| 		name = gs->name; |  | ||||||
|  |  | ||||||
| 	prepare_submodule_repo_env(&cp.env_array); |  | ||||||
| 	argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT); |  | ||||||
|  |  | ||||||
| 	if (opt->relative && opt->prefix_length) |  | ||||||
| 		argv_array_pushf(&cp.env_array, "%s=%s", |  | ||||||
| 				 GIT_TOPLEVEL_PREFIX_ENVIRONMENT, |  | ||||||
| 				 opt->prefix); |  | ||||||
|  |  | ||||||
| 	/* Add super prefix */ |  | ||||||
| 	argv_array_pushf(&cp.args, "--super-prefix=%s%s/", |  | ||||||
| 			 super_prefix ? super_prefix : "", |  | ||||||
| 			 name); |  | ||||||
| 	argv_array_push(&cp.args, "grep"); |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Add basename of parent project |  | ||||||
| 	 * When performing grep on a tree object the filename is prefixed |  | ||||||
| 	 * with the object's name: 'tree-name:filename'.  In order to |  | ||||||
| 	 * provide uniformity of output we want to pass the name of the |  | ||||||
| 	 * parent project's object name to the submodule so the submodule can |  | ||||||
| 	 * prefix its output with the parent's name and not its own OID. |  | ||||||
| 	 */ |  | ||||||
| 	if (gs->identifier && end_of_base) |  | ||||||
| 		argv_array_pushf(&cp.args, "--parent-basename=%.*s", |  | ||||||
| 				 (int) (end_of_base - gs->name), |  | ||||||
| 				 gs->name); |  | ||||||
|  |  | ||||||
| 	/* Add options */ |  | ||||||
| 	for (i = 0; i < submodule_options.argc; i++) { |  | ||||||
| 		/* |  | ||||||
| 		 * If there is a tree identifier for the submodule, add the |  | ||||||
| 		 * rev after adding the submodule options but before the |  | ||||||
| 		 * pathspecs.  To do this we listen for the '--' and insert the |  | ||||||
| 		 * oid before pushing the '--' onto the child process argv |  | ||||||
| 		 * array. |  | ||||||
| 		 */ |  | ||||||
| 		if (gs->identifier && |  | ||||||
| 		    !strcmp("--", submodule_options.argv[i])) { |  | ||||||
| 			argv_array_push(&cp.args, oid_to_hex(gs->identifier)); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		argv_array_push(&cp.args, submodule_options.argv[i]); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	cp.git_cmd = 1; |  | ||||||
| 	cp.dir = gs->path; |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Capture output to output buffer and check the return code from the |  | ||||||
| 	 * child process.  A '0' indicates a hit, a '1' indicates no hit and |  | ||||||
| 	 * anything else is an error. |  | ||||||
| 	 */ |  | ||||||
| 	status = capture_command(&cp, &child_output, 0); |  | ||||||
| 	if (status && (status != 1)) { |  | ||||||
| 		/* flush the buffer */ |  | ||||||
| 		write_or_die(1, child_output.buf, child_output.len); |  | ||||||
| 		die("process for submodule '%s' failed with exit code: %d", |  | ||||||
| 		    gs->name, status); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	opt->output(opt, child_output.buf, child_output.len); |  | ||||||
| 	strbuf_release(&child_output); |  | ||||||
| 	/* invert the return code to make a hit equal to 1 */ |  | ||||||
| 	return !status; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Prep grep structures for a submodule grep |  | ||||||
|  * oid: the oid of the submodule or NULL if using the working tree |  | ||||||
|  * filename: name of the submodule including tree name of parent |  | ||||||
|  * path: location of the submodule |  | ||||||
|  */ |  | ||||||
| static int grep_submodule(struct grep_opt *opt, const struct object_id *oid, |  | ||||||
| 			  const char *filename, const char *path) | 			  const char *filename, const char *path) | ||||||
| { | { | ||||||
| 	if (!is_submodule_active(the_repository, path)) | 	struct repository submodule; | ||||||
| 		return 0; | 	int hit; | ||||||
| 	if (!is_submodule_populated_gently(path, NULL)) { |  | ||||||
| 		/* |  | ||||||
| 		 * If searching history, check for the presence of the |  | ||||||
| 		 * submodule's gitdir before skipping the submodule. |  | ||||||
| 		 */ |  | ||||||
| 		if (oid) { |  | ||||||
| 			const struct submodule *sub = |  | ||||||
| 					submodule_from_path(null_sha1, path); |  | ||||||
| 			if (sub) |  | ||||||
| 				path = git_path("modules/%s", sub->name); |  | ||||||
|  |  | ||||||
| 			if (!(is_directory(path) && is_git_directory(path))) | 	if (!is_submodule_active(superproject, path)) | ||||||
| 				return 0; | 		return 0; | ||||||
| 		} else { |  | ||||||
| 			return 0; | 	if (repo_submodule_init(&submodule, superproject, path)) | ||||||
| 		} | 		return 0; | ||||||
|  |  | ||||||
|  | 	repo_read_gitmodules(&submodule); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * NEEDSWORK: This adds the submodule's object directory to the list of | ||||||
|  | 	 * alternates for the single in-memory object store.  This has some bad | ||||||
|  | 	 * consequences for memory (processed objects will never be freed) and | ||||||
|  | 	 * performance (this increases the number of pack files git has to pay | ||||||
|  | 	 * attention to, to the sum of the number of pack files in all the | ||||||
|  | 	 * repositories processed so far).  This can be removed once the object | ||||||
|  | 	 * store is no longer global and instead is a member of the repository | ||||||
|  | 	 * object. | ||||||
|  | 	 */ | ||||||
|  | 	add_to_alternates_memory(submodule.objectdir); | ||||||
|  |  | ||||||
|  | 	if (oid) { | ||||||
|  | 		struct object *object; | ||||||
|  | 		struct tree_desc tree; | ||||||
|  | 		void *data; | ||||||
|  | 		unsigned long size; | ||||||
|  | 		struct strbuf base = STRBUF_INIT; | ||||||
|  |  | ||||||
|  | 		object = parse_object_or_die(oid, oid_to_hex(oid)); | ||||||
|  |  | ||||||
|  | 		grep_read_lock(); | ||||||
|  | 		data = read_object_with_reference(object->oid.hash, tree_type, | ||||||
|  | 						  &size, NULL); | ||||||
|  | 		grep_read_unlock(); | ||||||
|  |  | ||||||
|  | 		if (!data) | ||||||
|  | 			die(_("unable to read tree (%s)"), oid_to_hex(&object->oid)); | ||||||
|  |  | ||||||
|  | 		strbuf_addstr(&base, filename); | ||||||
|  | 		strbuf_addch(&base, '/'); | ||||||
|  |  | ||||||
|  | 		init_tree_desc(&tree, data, size); | ||||||
|  | 		hit = grep_tree(opt, pathspec, &tree, &base, base.len, | ||||||
|  | 				object->type == OBJ_COMMIT, &submodule); | ||||||
|  | 		strbuf_release(&base); | ||||||
|  | 		free(data); | ||||||
|  | 	} else { | ||||||
|  | 		hit = grep_cache(opt, &submodule, pathspec, 1); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #ifndef NO_PTHREADS | 	repo_clear(&submodule); | ||||||
| 	if (num_threads) { | 	return hit; | ||||||
| 		add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid); |  | ||||||
| 		return 0; |  | ||||||
| 	} else |  | ||||||
| #endif |  | ||||||
| 	{ |  | ||||||
| 		struct grep_source gs; |  | ||||||
| 		int hit; |  | ||||||
|  |  | ||||||
| 		grep_source_init(&gs, GREP_SOURCE_SUBMODULE, |  | ||||||
| 				 filename, path, oid); |  | ||||||
| 		hit = grep_submodule_launch(opt, &gs); |  | ||||||
|  |  | ||||||
| 		grep_source_clear(&gs); |  | ||||||
| 		return hit; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, | static int grep_cache(struct grep_opt *opt, struct repository *repo, | ||||||
| 		      int cached) | 		      const struct pathspec *pathspec, int cached) | ||||||
| { | { | ||||||
| 	int hit = 0; | 	int hit = 0; | ||||||
| 	int nr; | 	int nr; | ||||||
| 	struct strbuf name = STRBUF_INIT; | 	struct strbuf name = STRBUF_INIT; | ||||||
| 	int name_base_len = 0; | 	int name_base_len = 0; | ||||||
| 	if (super_prefix) { | 	if (repo->submodule_prefix) { | ||||||
| 		name_base_len = strlen(super_prefix); | 		name_base_len = strlen(repo->submodule_prefix); | ||||||
| 		strbuf_addstr(&name, super_prefix); | 		strbuf_addstr(&name, repo->submodule_prefix); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	read_cache(); | 	repo_read_index(repo); | ||||||
|  |  | ||||||
| 	for (nr = 0; nr < active_nr; nr++) { | 	for (nr = 0; nr < repo->index->cache_nr; nr++) { | ||||||
| 		const struct cache_entry *ce = active_cache[nr]; | 		const struct cache_entry *ce = repo->index->cache[nr]; | ||||||
| 		strbuf_setlen(&name, name_base_len); | 		strbuf_setlen(&name, name_base_len); | ||||||
| 		strbuf_addstr(&name, ce->name); | 		strbuf_addstr(&name, ce->name); | ||||||
|  |  | ||||||
|  | @ -715,14 +498,14 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 			    ce_skip_worktree(ce)) { | 			    ce_skip_worktree(ce)) { | ||||||
| 				if (ce_stage(ce) || ce_intent_to_add(ce)) | 				if (ce_stage(ce) || ce_intent_to_add(ce)) | ||||||
| 					continue; | 					continue; | ||||||
| 				hit |= grep_oid(opt, &ce->oid, ce->name, | 				hit |= grep_oid(opt, &ce->oid, name.buf, | ||||||
| 						 0, ce->name); | 						 0, name.buf); | ||||||
| 			} else { | 			} else { | ||||||
| 				hit |= grep_file(opt, ce->name); | 				hit |= grep_file(opt, name.buf); | ||||||
| 			} | 			} | ||||||
| 		} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && | 		} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && | ||||||
| 			   submodule_path_match(pathspec, name.buf, NULL)) { | 			   submodule_path_match(pathspec, name.buf, NULL)) { | ||||||
| 			hit |= grep_submodule(opt, NULL, ce->name, ce->name); | 			hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name); | ||||||
| 		} else { | 		} else { | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  | @ -730,8 +513,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 		if (ce_stage(ce)) { | 		if (ce_stage(ce)) { | ||||||
| 			do { | 			do { | ||||||
| 				nr++; | 				nr++; | ||||||
| 			} while (nr < active_nr && | 			} while (nr < repo->index->cache_nr && | ||||||
| 				 !strcmp(ce->name, active_cache[nr]->name)); | 				 !strcmp(ce->name, repo->index->cache[nr]->name)); | ||||||
| 			nr--; /* compensate for loop control */ | 			nr--; /* compensate for loop control */ | ||||||
| 		} | 		} | ||||||
| 		if (hit && opt->status_only) | 		if (hit && opt->status_only) | ||||||
|  | @ -744,7 +527,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
|  |  | ||||||
| static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, | static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 		     struct tree_desc *tree, struct strbuf *base, int tn_len, | 		     struct tree_desc *tree, struct strbuf *base, int tn_len, | ||||||
| 		     int check_attr) | 		     int check_attr, struct repository *repo) | ||||||
| { | { | ||||||
| 	int hit = 0; | 	int hit = 0; | ||||||
| 	enum interesting match = entry_not_interesting; | 	enum interesting match = entry_not_interesting; | ||||||
|  | @ -752,8 +535,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 	int old_baselen = base->len; | 	int old_baselen = base->len; | ||||||
| 	struct strbuf name = STRBUF_INIT; | 	struct strbuf name = STRBUF_INIT; | ||||||
| 	int name_base_len = 0; | 	int name_base_len = 0; | ||||||
| 	if (super_prefix) { | 	if (repo->submodule_prefix) { | ||||||
| 		strbuf_addstr(&name, super_prefix); | 		strbuf_addstr(&name, repo->submodule_prefix); | ||||||
| 		name_base_len = name.len; | 		name_base_len = name.len; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -791,11 +574,11 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 			strbuf_addch(base, '/'); | 			strbuf_addch(base, '/'); | ||||||
| 			init_tree_desc(&sub, data, size); | 			init_tree_desc(&sub, data, size); | ||||||
| 			hit |= grep_tree(opt, pathspec, &sub, base, tn_len, | 			hit |= grep_tree(opt, pathspec, &sub, base, tn_len, | ||||||
| 					 check_attr); | 					 check_attr, repo); | ||||||
| 			free(data); | 			free(data); | ||||||
| 		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) { | 		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) { | ||||||
| 			hit |= grep_submodule(opt, entry.oid, base->buf, | 			hit |= grep_submodule(opt, repo, pathspec, entry.oid, | ||||||
| 					      base->buf + tn_len); | 					      base->buf, base->buf + tn_len); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		strbuf_setlen(base, old_baselen); | 		strbuf_setlen(base, old_baselen); | ||||||
|  | @ -809,7 +592,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| } | } | ||||||
|  |  | ||||||
| static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, | static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 		       struct object *obj, const char *name, const char *path) | 		       struct object *obj, const char *name, const char *path, | ||||||
|  | 		       struct repository *repo) | ||||||
| { | { | ||||||
| 	if (obj->type == OBJ_BLOB) | 	if (obj->type == OBJ_BLOB) | ||||||
| 		return grep_oid(opt, &obj->oid, name, 0, path); | 		return grep_oid(opt, &obj->oid, name, 0, path); | ||||||
|  | @ -828,10 +612,6 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 		if (!data) | 		if (!data) | ||||||
| 			die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid)); | 			die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid)); | ||||||
|  |  | ||||||
| 		/* Use parent's name as base when recursing submodules */ |  | ||||||
| 		if (recurse_submodules && parent_basename) |  | ||||||
| 			name = parent_basename; |  | ||||||
|  |  | ||||||
| 		len = name ? strlen(name) : 0; | 		len = name ? strlen(name) : 0; | ||||||
| 		strbuf_init(&base, PATH_MAX + len + 1); | 		strbuf_init(&base, PATH_MAX + len + 1); | ||||||
| 		if (len) { | 		if (len) { | ||||||
|  | @ -840,7 +620,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 		} | 		} | ||||||
| 		init_tree_desc(&tree, data, size); | 		init_tree_desc(&tree, data, size); | ||||||
| 		hit = grep_tree(opt, pathspec, &tree, &base, base.len, | 		hit = grep_tree(opt, pathspec, &tree, &base, base.len, | ||||||
| 				obj->type == OBJ_COMMIT); | 				obj->type == OBJ_COMMIT, repo); | ||||||
| 		strbuf_release(&base); | 		strbuf_release(&base); | ||||||
| 		free(data); | 		free(data); | ||||||
| 		return hit; | 		return hit; | ||||||
|  | @ -849,6 +629,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| } | } | ||||||
|  |  | ||||||
| static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, | static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
|  | 			struct repository *repo, | ||||||
| 			const struct object_array *list) | 			const struct object_array *list) | ||||||
| { | { | ||||||
| 	unsigned int i; | 	unsigned int i; | ||||||
|  | @ -864,7 +645,8 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, | ||||||
| 			submodule_free(); | 			submodule_free(); | ||||||
| 			gitmodules_config_sha1(real_obj->oid.hash); | 			gitmodules_config_sha1(real_obj->oid.hash); | ||||||
| 		} | 		} | ||||||
| 		if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) { | 		if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path, | ||||||
|  | 				repo)) { | ||||||
| 			hit = 1; | 			hit = 1; | ||||||
| 			if (opt->status_only) | 			if (opt->status_only) | ||||||
| 				break; | 				break; | ||||||
|  | @ -1005,9 +787,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) | ||||||
| 			    N_("ignore files specified via '.gitignore'"), 1), | 			    N_("ignore files specified via '.gitignore'"), 1), | ||||||
| 		OPT_BOOL(0, "recurse-submodules", &recurse_submodules, | 		OPT_BOOL(0, "recurse-submodules", &recurse_submodules, | ||||||
| 			 N_("recursively search in each submodule")), | 			 N_("recursively search in each submodule")), | ||||||
| 		OPT_STRING(0, "parent-basename", &parent_basename, |  | ||||||
| 			   N_("basename"), |  | ||||||
| 			   N_("prepend parent project's basename to output")), |  | ||||||
| 		OPT_GROUP(""), | 		OPT_GROUP(""), | ||||||
| 		OPT_BOOL('v', "invert-match", &opt.invert, | 		OPT_BOOL('v', "invert-match", &opt.invert, | ||||||
| 			N_("show non-matching lines")), | 			N_("show non-matching lines")), | ||||||
|  | @ -1112,7 +891,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) | ||||||
| 	init_grep_defaults(); | 	init_grep_defaults(); | ||||||
| 	git_config(grep_cmd_config, NULL); | 	git_config(grep_cmd_config, NULL); | ||||||
| 	grep_init(&opt, prefix); | 	grep_init(&opt, prefix); | ||||||
| 	super_prefix = get_super_prefix(); |  | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * If there is no -- then the paths must exist in the working | 	 * If there is no -- then the paths must exist in the working | ||||||
|  | @ -1272,9 +1050,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) | ||||||
|  |  | ||||||
| 	if (recurse_submodules) { | 	if (recurse_submodules) { | ||||||
| 		gitmodules_config(); | 		gitmodules_config(); | ||||||
| 		compile_submodule_options(&opt, argv + i, cached, untracked, |  | ||||||
| 					  opt_exclude, use_index, |  | ||||||
| 					  pattern_type_arg); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (show_in_pager && (cached || list.nr)) | 	if (show_in_pager && (cached || list.nr)) | ||||||
|  | @ -1318,11 +1093,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix) | ||||||
| 		if (!cached) | 		if (!cached) | ||||||
| 			setup_work_tree(); | 			setup_work_tree(); | ||||||
|  |  | ||||||
| 		hit = grep_cache(&opt, &pathspec, cached); | 		hit = grep_cache(&opt, the_repository, &pathspec, cached); | ||||||
| 	} else { | 	} else { | ||||||
| 		if (cached) | 		if (cached) | ||||||
| 			die(_("both --cached and trees are given.")); | 			die(_("both --cached and trees are given.")); | ||||||
| 		hit = grep_objects(&opt, &pathspec, &list); |  | ||||||
|  | 		hit = grep_objects(&opt, &pathspec, the_repository, &list); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (num_threads) | 	if (num_threads) | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										1
									
								
								cache.h
								
								
								
								
							|  | @ -417,7 +417,6 @@ static inline enum object_type object_type(unsigned int mode) | ||||||
| #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE" | #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE" | ||||||
| #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX" | #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX" | ||||||
| #define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX" | #define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX" | ||||||
| #define GIT_TOPLEVEL_PREFIX_ENVIRONMENT "GIT_INTERNAL_TOPLEVEL_PREFIX" |  | ||||||
| #define DEFAULT_GIT_DIR_ENVIRONMENT ".git" | #define DEFAULT_GIT_DIR_ENVIRONMENT ".git" | ||||||
| #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" | #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" | ||||||
| #define INDEX_ENVIRONMENT "GIT_INDEX_FILE" | #define INDEX_ENVIRONMENT "GIT_INDEX_FILE" | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								git.c
								
								
								
								
							
							
						
						
									
										2
									
								
								git.c
								
								
								
								
							|  | @ -392,7 +392,7 @@ static struct cmd_struct commands[] = { | ||||||
| 	{ "fsck-objects", cmd_fsck, RUN_SETUP }, | 	{ "fsck-objects", cmd_fsck, RUN_SETUP }, | ||||||
| 	{ "gc", cmd_gc, RUN_SETUP }, | 	{ "gc", cmd_gc, RUN_SETUP }, | ||||||
| 	{ "get-tar-commit-id", cmd_get_tar_commit_id }, | 	{ "get-tar-commit-id", cmd_get_tar_commit_id }, | ||||||
| 	{ "grep", cmd_grep, RUN_SETUP_GENTLY | SUPPORT_SUPER_PREFIX }, | 	{ "grep", cmd_grep, RUN_SETUP_GENTLY }, | ||||||
| 	{ "hash-object", cmd_hash_object }, | 	{ "hash-object", cmd_hash_object }, | ||||||
| 	{ "help", cmd_help }, | 	{ "help", cmd_help }, | ||||||
| 	{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY }, | 	{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY }, | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								grep.c
								
								
								
								
							
							
						
						
									
										13
									
								
								grep.c
								
								
								
								
							|  | @ -1927,16 +1927,6 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type, | ||||||
| 	case GREP_SOURCE_FILE: | 	case GREP_SOURCE_FILE: | ||||||
| 		gs->identifier = xstrdup(identifier); | 		gs->identifier = xstrdup(identifier); | ||||||
| 		break; | 		break; | ||||||
| 	case GREP_SOURCE_SUBMODULE: |  | ||||||
| 		if (!identifier) { |  | ||||||
| 			gs->identifier = NULL; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		/* |  | ||||||
| 		 * FALL THROUGH |  | ||||||
| 		 * If the identifier is non-NULL (in the submodule case) it |  | ||||||
| 		 * will be a SHA1 that needs to be copied. |  | ||||||
| 		 */ |  | ||||||
| 	case GREP_SOURCE_OID: | 	case GREP_SOURCE_OID: | ||||||
| 		gs->identifier = oiddup(identifier); | 		gs->identifier = oiddup(identifier); | ||||||
| 		break; | 		break; | ||||||
|  | @ -1959,7 +1949,6 @@ void grep_source_clear_data(struct grep_source *gs) | ||||||
| 	switch (gs->type) { | 	switch (gs->type) { | ||||||
| 	case GREP_SOURCE_FILE: | 	case GREP_SOURCE_FILE: | ||||||
| 	case GREP_SOURCE_OID: | 	case GREP_SOURCE_OID: | ||||||
| 	case GREP_SOURCE_SUBMODULE: |  | ||||||
| 		FREE_AND_NULL(gs->buf); | 		FREE_AND_NULL(gs->buf); | ||||||
| 		gs->size = 0; | 		gs->size = 0; | ||||||
| 		break; | 		break; | ||||||
|  | @ -2030,8 +2019,6 @@ static int grep_source_load(struct grep_source *gs) | ||||||
| 		return grep_source_load_oid(gs); | 		return grep_source_load_oid(gs); | ||||||
| 	case GREP_SOURCE_BUF: | 	case GREP_SOURCE_BUF: | ||||||
| 		return gs->buf ? 0 : -1; | 		return gs->buf ? 0 : -1; | ||||||
| 	case GREP_SOURCE_SUBMODULE: |  | ||||||
| 		break; |  | ||||||
| 	} | 	} | ||||||
| 	die("BUG: invalid grep_source type to load"); | 	die("BUG: invalid grep_source type to load"); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								grep.h
								
								
								
								
							
							
						
						
									
										1
									
								
								grep.h
								
								
								
								
							|  | @ -193,7 +193,6 @@ struct grep_source { | ||||||
| 		GREP_SOURCE_OID, | 		GREP_SOURCE_OID, | ||||||
| 		GREP_SOURCE_FILE, | 		GREP_SOURCE_FILE, | ||||||
| 		GREP_SOURCE_BUF, | 		GREP_SOURCE_BUF, | ||||||
| 		GREP_SOURCE_SUBMODULE, |  | ||||||
| 	} type; | 	} type; | ||||||
| 	void *identifier; | 	void *identifier; | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								setup.c
								
								
								
								
							
							
						
						
									
										12
									
								
								setup.c
								
								
								
								
							|  | @ -1027,7 +1027,7 @@ const char *setup_git_directory_gently(int *nongit_ok) | ||||||
| { | { | ||||||
| 	static struct strbuf cwd = STRBUF_INIT; | 	static struct strbuf cwd = STRBUF_INIT; | ||||||
| 	struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT; | 	struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT; | ||||||
| 	const char *prefix, *env_prefix; | 	const char *prefix; | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * We may have read an incomplete configuration before | 	 * We may have read an incomplete configuration before | ||||||
|  | @ -1085,16 +1085,6 @@ const char *setup_git_directory_gently(int *nongit_ok) | ||||||
| 		die("BUG: unhandled setup_git_directory_1() result"); | 		die("BUG: unhandled setup_git_directory_1() result"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * NEEDSWORK: This was a hack in order to get ls-files and grep to have |  | ||||||
| 	 * properly formated output when recursing submodules.  Once ls-files |  | ||||||
| 	 * and grep have been changed to perform this recursing in-process this |  | ||||||
| 	 * needs to be removed. |  | ||||||
| 	 */ |  | ||||||
| 	env_prefix = getenv(GIT_TOPLEVEL_PREFIX_ENVIRONMENT); |  | ||||||
| 	if (env_prefix) |  | ||||||
| 		prefix = env_prefix; |  | ||||||
|  |  | ||||||
| 	if (prefix) | 	if (prefix) | ||||||
| 		setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1); | 		setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1); | ||||||
| 	else | 	else | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Brandon Williams
						Brandon Williams