grep: drop pathspec_matches() in favor of tree_entry_interesting()
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
		 Nguyễn Thái Ngọc Duy
					Nguyễn Thái Ngọc Duy
				
			
				
					committed by
					
						 Junio C Hamano
						Junio C Hamano
					
				
			
			
				
	
			
			
			 Junio C Hamano
						Junio C Hamano
					
				
			
						parent
						
							e5e062b6dc
						
					
				
				
					commit
					1376e50723
				
			
							
								
								
									
										125
									
								
								builtin/grep.c
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								builtin/grep.c
									
									
									
									
									
								
							| @ -329,106 +329,6 @@ static int grep_config(const char *var, const char *value, void *cb) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Return non-zero if max_depth is negative or path has no more then max_depth |  | ||||||
|  * slashes. |  | ||||||
|  */ |  | ||||||
| static int accept_subdir(const char *path, int max_depth) |  | ||||||
| { |  | ||||||
| 	if (max_depth < 0) |  | ||||||
| 		return 1; |  | ||||||
|  |  | ||||||
| 	while ((path = strchr(path, '/')) != NULL) { |  | ||||||
| 		max_depth--; |  | ||||||
| 		if (max_depth < 0) |  | ||||||
| 			return 0; |  | ||||||
| 		path++; |  | ||||||
| 	} |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Return non-zero if name is a subdirectory of match and is not too deep. |  | ||||||
|  */ |  | ||||||
| static int is_subdir(const char *name, int namelen, |  | ||||||
| 		const char *match, int matchlen, int max_depth) |  | ||||||
| { |  | ||||||
| 	if (matchlen > namelen || strncmp(name, match, matchlen)) |  | ||||||
| 		return 0; |  | ||||||
|  |  | ||||||
| 	if (name[matchlen] == '\0') /* exact match */ |  | ||||||
| 		return 1; |  | ||||||
|  |  | ||||||
| 	if (!matchlen || match[matchlen-1] == '/' || name[matchlen] == '/') |  | ||||||
| 		return accept_subdir(name + matchlen + 1, max_depth); |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * git grep pathspecs are somewhat different from diff-tree pathspecs; |  | ||||||
|  * pathname wildcards are allowed. |  | ||||||
|  */ |  | ||||||
| static int pathspec_matches(const char **paths, const char *name, int max_depth) |  | ||||||
| { |  | ||||||
| 	int namelen, i; |  | ||||||
| 	if (!paths || !*paths) |  | ||||||
| 		return accept_subdir(name, max_depth); |  | ||||||
| 	namelen = strlen(name); |  | ||||||
| 	for (i = 0; paths[i]; i++) { |  | ||||||
| 		const char *match = paths[i]; |  | ||||||
| 		int matchlen = strlen(match); |  | ||||||
| 		const char *cp, *meta; |  | ||||||
|  |  | ||||||
| 		if (is_subdir(name, namelen, match, matchlen, max_depth)) |  | ||||||
| 			return 1; |  | ||||||
| 		if (!fnmatch(match, name, 0)) |  | ||||||
| 			return 1; |  | ||||||
| 		if (name[namelen-1] != '/') |  | ||||||
| 			continue; |  | ||||||
|  |  | ||||||
| 		/* We are being asked if the directory ("name") is worth |  | ||||||
| 		 * descending into. |  | ||||||
| 		 * |  | ||||||
| 		 * Find the longest leading directory name that does |  | ||||||
| 		 * not have metacharacter in the pathspec; the name |  | ||||||
| 		 * we are looking at must overlap with that directory. |  | ||||||
| 		 */ |  | ||||||
| 		for (cp = match, meta = NULL; cp - match < matchlen; cp++) { |  | ||||||
| 			char ch = *cp; |  | ||||||
| 			if (ch == '*' || ch == '[' || ch == '?') { |  | ||||||
| 				meta = cp; |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if (!meta) |  | ||||||
| 			meta = cp; /* fully literal */ |  | ||||||
|  |  | ||||||
| 		if (namelen <= meta - match) { |  | ||||||
| 			/* Looking at "Documentation/" and |  | ||||||
| 			 * the pattern says "Documentation/howto/", or |  | ||||||
| 			 * "Documentation/diff*.txt".  The name we |  | ||||||
| 			 * have should match prefix. |  | ||||||
| 			 */ |  | ||||||
| 			if (!memcmp(match, name, namelen)) |  | ||||||
| 				return 1; |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (meta - match < namelen) { |  | ||||||
| 			/* Looking at "Documentation/howto/" and |  | ||||||
| 			 * the pattern says "Documentation/h*"; |  | ||||||
| 			 * match up to "Do.../h"; this avoids descending |  | ||||||
| 			 * into "Documentation/technical/". |  | ||||||
| 			 */ |  | ||||||
| 			if (!memcmp(match, name, meta - match)) |  | ||||||
| 				return 1; |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) | static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) | ||||||
| { | { | ||||||
| 	void *data; | 	void *data; | ||||||
| @ -621,25 +521,24 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int | |||||||
| 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 hit = 0; | 	int hit = 0, matched = 0; | ||||||
| 	struct name_entry entry; | 	struct name_entry entry; | ||||||
| 	int old_baselen = base->len; | 	int old_baselen = base->len; | ||||||
|  |  | ||||||
| 	while (tree_entry(tree, &entry)) { | 	while (tree_entry(tree, &entry)) { | ||||||
| 		int te_len = tree_entry_len(entry.path, entry.sha1); | 		int te_len = tree_entry_len(entry.path, entry.sha1); | ||||||
|  |  | ||||||
|  | 		if (matched != 2) { | ||||||
|  | 			matched = tree_entry_interesting(&entry, base, tn_len, pathspec); | ||||||
|  | 			if (matched == -1) | ||||||
|  | 				break; /* no more matches */ | ||||||
|  | 			if (!matched) | ||||||
|  | 				continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		strbuf_add(base, entry.path, te_len); | 		strbuf_add(base, entry.path, te_len); | ||||||
|  |  | ||||||
| 		if (S_ISDIR(entry.mode)) | 		if (S_ISREG(entry.mode)) { | ||||||
| 			/* Match "abc/" against pathspec to |  | ||||||
| 			 * decide if we want to descend into "abc" |  | ||||||
| 			 * directory. |  | ||||||
| 			 */ |  | ||||||
| 			strbuf_addch(base, '/'); |  | ||||||
|  |  | ||||||
| 		if (!pathspec_matches(pathspec->raw, base->buf + tn_len, opt->max_depth)) |  | ||||||
| 			; |  | ||||||
| 		else if (S_ISREG(entry.mode)) { |  | ||||||
| 			hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len); | 			hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len); | ||||||
| 		} | 		} | ||||||
| 		else if (S_ISDIR(entry.mode)) { | 		else if (S_ISDIR(entry.mode)) { | ||||||
| @ -652,6 +551,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, | |||||||
| 			if (!data) | 			if (!data) | ||||||
| 				die("unable to read tree (%s)", | 				die("unable to read tree (%s)", | ||||||
| 				    sha1_to_hex(entry.sha1)); | 				    sha1_to_hex(entry.sha1)); | ||||||
|  |  | ||||||
|  | 			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); | ||||||
| 			free(data); | 			free(data); | ||||||
| @ -1058,6 +959,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) | |||||||
| 		paths[1] = NULL; | 		paths[1] = NULL; | ||||||
| 	} | 	} | ||||||
| 	init_pathspec(&pathspec, paths); | 	init_pathspec(&pathspec, paths); | ||||||
|  | 	pathspec.max_depth = opt.max_depth; | ||||||
|  | 	pathspec.recursive = 1; | ||||||
|  |  | ||||||
| 	if (show_in_pager && (cached || list.nr)) | 	if (show_in_pager && (cached || list.nr)) | ||||||
| 		die("--open-files-in-pager only works on the worktree"); | 		die("--open-files-in-pager only works on the worktree"); | ||||||
|  | |||||||
| @ -72,7 +72,7 @@ static void show_tree(struct diff_options *opt, const char *prefix, | |||||||
| 		if (all_interesting) | 		if (all_interesting) | ||||||
| 			show = 1; | 			show = 1; | ||||||
| 		else { | 		else { | ||||||
| 			show = tree_entry_interesting(&desc->entry, base, | 			show = tree_entry_interesting(&desc->entry, base, 0, | ||||||
| 						      &opt->pathspec); | 						      &opt->pathspec); | ||||||
| 			if (show == 2) | 			if (show == 2) | ||||||
| 				all_interesting = 1; | 				all_interesting = 1; | ||||||
| @ -124,7 +124,7 @@ static void skip_uninteresting(struct tree_desc *t, struct strbuf *base, | |||||||
| 			       struct diff_options *opt, int *all_interesting) | 			       struct diff_options *opt, int *all_interesting) | ||||||
| { | { | ||||||
| 	while (t->size) { | 	while (t->size) { | ||||||
| 		int show = tree_entry_interesting(&t->entry, base, &opt->pathspec); | 		int show = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec); | ||||||
| 		if (show == 2) | 		if (show == 2) | ||||||
| 			*all_interesting = 1; | 			*all_interesting = 1; | ||||||
| 		if (!show) { | 		if (!show) { | ||||||
|  | |||||||
							
								
								
									
										24
									
								
								tree-walk.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								tree-walk.c
									
									
									
									
									
								
							| @ -544,7 +544,8 @@ static int match_dir_prefix(const char *base, int baselen, | |||||||
| /* | /* | ||||||
|  * Is a tree entry interesting given the pathspec we have? |  * Is a tree entry interesting given the pathspec we have? | ||||||
|  * |  * | ||||||
|  * Pre-condition: baselen == 0 || base[baselen-1] == '/' |  * Pre-condition: either baselen == base_offset (i.e. empty path) | ||||||
|  |  * or base[baselen-1] == '/' (i.e. with trailing slash). | ||||||
|  * |  * | ||||||
|  * Return: |  * Return: | ||||||
|  *  - 2 for "yes, and all subsequent entries will be" |  *  - 2 for "yes, and all subsequent entries will be" | ||||||
| @ -553,44 +554,45 @@ static int match_dir_prefix(const char *base, int baselen, | |||||||
|  *  - negative for "no, and no subsequent entries will be either" |  *  - negative for "no, and no subsequent entries will be either" | ||||||
|  */ |  */ | ||||||
| int tree_entry_interesting(const struct name_entry *entry, | int tree_entry_interesting(const struct name_entry *entry, | ||||||
| 			   struct strbuf *base, | 			   struct strbuf *base, int base_offset, | ||||||
| 			   const struct pathspec *ps) | 			   const struct pathspec *ps) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 	int pathlen, baselen = base->len; | 	int pathlen, baselen = base->len - base_offset; | ||||||
| 	int never_interesting = ps->has_wildcard ? 0 : -1; | 	int never_interesting = ps->has_wildcard ? 0 : -1; | ||||||
|  |  | ||||||
| 	if (!ps->nr) { | 	if (!ps->nr) { | ||||||
| 		if (!ps->recursive || ps->max_depth == -1) | 		if (!ps->recursive || ps->max_depth == -1) | ||||||
| 			return 2; | 			return 2; | ||||||
| 		return !!within_depth(base->buf, baselen, | 		return !!within_depth(base->buf + base_offset, baselen, | ||||||
| 				      !!S_ISDIR(entry->mode), | 				      !!S_ISDIR(entry->mode), | ||||||
| 				      ps->max_depth); | 				      ps->max_depth); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	pathlen = tree_entry_len(entry->path, entry->sha1); | 	pathlen = tree_entry_len(entry->path, entry->sha1); | ||||||
|  |  | ||||||
| 	for (i = ps->nr-1; i >= 0; i--) { | 	for (i = ps->nr - 1; i >= 0; i--) { | ||||||
| 		const struct pathspec_item *item = ps->items+i; | 		const struct pathspec_item *item = ps->items+i; | ||||||
| 		const char *match = item->match; | 		const char *match = item->match; | ||||||
|  | 		const char *base_str = base->buf + base_offset; | ||||||
| 		int matchlen = item->len; | 		int matchlen = item->len; | ||||||
|  |  | ||||||
| 		if (baselen >= matchlen) { | 		if (baselen >= matchlen) { | ||||||
| 			/* If it doesn't match, move along... */ | 			/* If it doesn't match, move along... */ | ||||||
| 			if (!match_dir_prefix(base->buf, baselen, match, matchlen)) | 			if (!match_dir_prefix(base_str, baselen, match, matchlen)) | ||||||
| 				goto match_wildcards; | 				goto match_wildcards; | ||||||
|  |  | ||||||
| 			if (!ps->recursive || ps->max_depth == -1) | 			if (!ps->recursive || ps->max_depth == -1) | ||||||
| 				return 2; | 				return 2; | ||||||
|  |  | ||||||
| 			return !!within_depth(base->buf + matchlen + 1, | 			return !!within_depth(base_str + matchlen + 1, | ||||||
| 					      baselen - matchlen - 1, | 					      baselen - matchlen - 1, | ||||||
| 					      !!S_ISDIR(entry->mode), | 					      !!S_ISDIR(entry->mode), | ||||||
| 					      ps->max_depth); | 					      ps->max_depth); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		/* Does the base match? */ | 		/* Does the base match? */ | ||||||
| 		if (!strncmp(base->buf, match, baselen)) { | 		if (!strncmp(base_str, match, baselen)) { | ||||||
| 			if (match_entry(entry, pathlen, | 			if (match_entry(entry, pathlen, | ||||||
| 					match + baselen, matchlen - baselen, | 					match + baselen, matchlen - baselen, | ||||||
| 					&never_interesting)) | 					&never_interesting)) | ||||||
| @ -622,11 +624,11 @@ match_wildcards: | |||||||
|  |  | ||||||
| 		strbuf_add(base, entry->path, pathlen); | 		strbuf_add(base, entry->path, pathlen); | ||||||
|  |  | ||||||
| 		if (!fnmatch(match, base->buf, 0)) { | 		if (!fnmatch(match, base->buf + base_offset, 0)) { | ||||||
| 			strbuf_setlen(base, baselen); | 			strbuf_setlen(base, base_offset + baselen); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 		strbuf_setlen(base, baselen); | 		strbuf_setlen(base, base_offset + baselen); | ||||||
|  |  | ||||||
| 		/* | 		/* | ||||||
| 		 * Match all directories. We'll try to match files | 		 * Match all directories. We'll try to match files | ||||||
|  | |||||||
| @ -60,6 +60,6 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru | |||||||
| 	return info->pathlen + tree_entry_len(n->path, n->sha1); | 	return info->pathlen + tree_entry_len(n->path, n->sha1); | ||||||
| } | } | ||||||
|  |  | ||||||
| extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, const struct pathspec *ps); | extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, int, const struct pathspec *ps); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user