tree_entry_interesting(): support wildcard matching
never_interesting optimization is disabled if there is any wildcard pathspec, even if it only matches exactly on trees. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									86e4ca69e3
								
							
						
					
					
						commit
						d38f28093e
					
				
							
								
								
									
										2
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										2
									
								
								cache.h
								
								
								
								
							|  | @ -503,11 +503,13 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct | ||||||
| struct pathspec { | struct pathspec { | ||||||
| 	const char **raw; /* get_pathspec() result, not freed by free_pathspec() */ | 	const char **raw; /* get_pathspec() result, not freed by free_pathspec() */ | ||||||
| 	int nr; | 	int nr; | ||||||
|  | 	int has_wildcard:1; | ||||||
| 	int recursive:1; | 	int recursive:1; | ||||||
| 	int max_depth; | 	int max_depth; | ||||||
| 	struct pathspec_item { | 	struct pathspec_item { | ||||||
| 		const char *match; | 		const char *match; | ||||||
| 		int len; | 		int len; | ||||||
|  | 		int has_wildcard:1; | ||||||
| 	} *items; | 	} *items; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								dir.c
								
								
								
								
							
							
						
						
									
										3
									
								
								dir.c
								
								
								
								
							|  | @ -1197,6 +1197,9 @@ int init_pathspec(struct pathspec *pathspec, const char **paths) | ||||||
|  |  | ||||||
| 		item->match = path; | 		item->match = path; | ||||||
| 		item->len = strlen(path); | 		item->len = strlen(path); | ||||||
|  | 		item->has_wildcard = !no_wildcard(path); | ||||||
|  | 		if (item->has_wildcard) | ||||||
|  | 			pathspec->has_wildcard = 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	qsort(pathspec->items, pathspec->nr, | 	qsort(pathspec->items, pathspec->nr, | ||||||
|  |  | ||||||
|  | @ -70,4 +70,18 @@ test_expect_success 'diff-tree pathspec' ' | ||||||
| 	test_cmp expected current | 	test_cmp expected current | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 | ||||||
|  |  | ||||||
|  | test_expect_success 'diff-tree with wildcard shows dir also matches' ' | ||||||
|  | 	git diff-tree --name-only $EMPTY_TREE $tree -- "f*" >result && | ||||||
|  | 	echo file0 >expected && | ||||||
|  | 	test_cmp expected result | ||||||
|  | ' | ||||||
|  |  | ||||||
|  | test_expect_success 'diff-tree -r with wildcard' ' | ||||||
|  | 	git diff-tree -r --name-only $EMPTY_TREE $tree -- "*file1" >result && | ||||||
|  | 	echo path1/file1 >expected && | ||||||
|  | 	test_cmp expected result | ||||||
|  | ' | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								tree-walk.c
								
								
								
								
							
							
						
						
									
										30
									
								
								tree-walk.c
								
								
								
								
							|  | @ -553,12 +553,12 @@ 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, | ||||||
| 			   const struct strbuf *base, | 			   struct strbuf *base, | ||||||
| 			   const struct pathspec *ps) | 			   const struct pathspec *ps) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 	int pathlen, baselen = base->len; | 	int pathlen, baselen = base->len; | ||||||
| 	int never_interesting = -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) | ||||||
|  | @ -578,7 +578,7 @@ int tree_entry_interesting(const struct name_entry *entry, | ||||||
| 		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->buf, baselen, match, matchlen)) | ||||||
| 				continue; | 				goto match_wildcards; | ||||||
|  |  | ||||||
| 			if (!ps->recursive || ps->max_depth == -1) | 			if (!ps->recursive || ps->max_depth == -1) | ||||||
| 				return 2; | 				return 2; | ||||||
|  | @ -596,6 +596,30 @@ int tree_entry_interesting(const struct name_entry *entry, | ||||||
| 					&never_interesting)) | 					&never_interesting)) | ||||||
| 				return 1; | 				return 1; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | match_wildcards: | ||||||
|  | 		if (!ps->items[i].has_wildcard) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		 * Concatenate base and entry->path into one and do | ||||||
|  | 		 * fnmatch() on it. | ||||||
|  | 		 */ | ||||||
|  |  | ||||||
|  | 		strbuf_add(base, entry->path, pathlen); | ||||||
|  |  | ||||||
|  | 		if (!fnmatch(match, base->buf, 0)) { | ||||||
|  | 			strbuf_setlen(base, baselen); | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
|  | 		strbuf_setlen(base, baselen); | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		 * Match all directories. We'll try to match files | ||||||
|  | 		 * later on. | ||||||
|  | 		 */ | ||||||
|  | 		if (ps->recursive && S_ISDIR(entry->mode)) | ||||||
|  | 			return 1; | ||||||
| 	} | 	} | ||||||
| 	return never_interesting; /* No matches */ | 	return never_interesting; /* No matches */ | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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 *, const struct strbuf *, const struct pathspec *ps); | extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, const struct pathspec *ps); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy