Reimplement read_tree_recursive() using tree_entry_interesting()
read_tree_recursive() uses a very similar function, match_tree_entry, to tree_entry_interesting() to do its path matching. This patch kills match_tree_entry() in favor of tree_entry_interesting(). match_tree_entry(), like older version of tree_entry_interesting(), does not support wildcard matching. New read_tree_recursive() retains this behavior by forcing all pathspecs literal. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									f2cfc9c81e
								
							
						
					
					
						commit
						ffd31f661d
					
				
							
								
								
									
										168
									
								
								tree.c
								
								
								
								
							
							
						
						
									
										168
									
								
								tree.c
								
								
								
								
							|  | @ -45,51 +45,69 @@ static int read_one_entry_quick(const unsigned char *sha1, const char *base, int | |||
| 				  ADD_CACHE_JUST_APPEND); | ||||
| } | ||||
|  | ||||
| static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, const char **paths) | ||||
| static int read_tree_1(struct tree *tree, struct strbuf *base, | ||||
| 		       int stage, struct pathspec *pathspec, | ||||
| 		       read_tree_fn_t fn, void *context) | ||||
| { | ||||
| 	const char *match; | ||||
| 	int pathlen; | ||||
| 	struct tree_desc desc; | ||||
| 	struct name_entry entry; | ||||
| 	unsigned char sha1[20]; | ||||
| 	int len, retval = 0, oldlen = base->len; | ||||
|  | ||||
| 	if (!paths) | ||||
| 		return 1; | ||||
| 	pathlen = strlen(path); | ||||
| 	while ((match = *paths++) != NULL) { | ||||
| 		int matchlen = strlen(match); | ||||
| 	if (parse_tree(tree)) | ||||
| 		return -1; | ||||
|  | ||||
| 		if (baselen >= matchlen) { | ||||
| 			/* If it doesn't match, move along... */ | ||||
| 			if (strncmp(base, match, matchlen)) | ||||
| 				continue; | ||||
| 			/* pathspecs match only at the directory boundaries */ | ||||
| 			if (!matchlen || | ||||
| 			    baselen == matchlen || | ||||
| 			    base[matchlen] == '/' || | ||||
| 			    match[matchlen - 1] == '/') | ||||
| 				return 1; | ||||
| 			continue; | ||||
| 		} | ||||
| 	init_tree_desc(&desc, tree->buffer, tree->size); | ||||
|  | ||||
| 		/* Does the base match? */ | ||||
| 		if (strncmp(base, match, baselen)) | ||||
| 			continue; | ||||
|  | ||||
| 		match += baselen; | ||||
| 		matchlen -= baselen; | ||||
|  | ||||
| 		if (pathlen > matchlen) | ||||
| 			continue; | ||||
|  | ||||
| 		if (matchlen > pathlen) { | ||||
| 			if (match[pathlen] != '/') | ||||
| 				continue; | ||||
| 			if (!S_ISDIR(mode)) | ||||
| 	while (tree_entry(&desc, &entry)) { | ||||
| 		if (retval != 2) { | ||||
| 			retval = tree_entry_interesting(&entry, base, 0, pathspec); | ||||
| 			if (retval < 0) | ||||
| 				break; | ||||
| 			if (retval == 0) | ||||
| 				continue; | ||||
| 		} | ||||
|  | ||||
| 		if (strncmp(path, match, pathlen)) | ||||
| 		switch (fn(entry.sha1, base->buf, base->len, | ||||
| 			   entry.path, entry.mode, stage, context)) { | ||||
| 		case 0: | ||||
| 			continue; | ||||
| 		case READ_TREE_RECURSIVE: | ||||
| 			break; | ||||
| 		default: | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		if (S_ISDIR(entry.mode)) | ||||
| 			hashcpy(sha1, entry.sha1); | ||||
| 		else if (S_ISGITLINK(entry.mode)) { | ||||
| 			struct commit *commit; | ||||
|  | ||||
| 			commit = lookup_commit(entry.sha1); | ||||
| 			if (!commit) | ||||
| 				die("Commit %s in submodule path %s%s not found", | ||||
| 				    sha1_to_hex(entry.sha1), | ||||
| 				    base->buf, entry.path); | ||||
|  | ||||
| 			if (parse_commit(commit)) | ||||
| 				die("Invalid commit %s in submodule path %s%s", | ||||
| 				    sha1_to_hex(entry.sha1), | ||||
| 				    base->buf, entry.path); | ||||
|  | ||||
| 			hashcpy(sha1, commit->tree->object.sha1); | ||||
| 		} | ||||
| 		else | ||||
| 			continue; | ||||
|  | ||||
| 		return 1; | ||||
| 		len = tree_entry_len(entry.path, entry.sha1); | ||||
| 		strbuf_add(base, entry.path, len); | ||||
| 		strbuf_addch(base, '/'); | ||||
| 		retval = read_tree_1(lookup_tree(sha1), | ||||
| 				     base, stage, pathspec, | ||||
| 				     fn, context); | ||||
| 		strbuf_setlen(base, oldlen); | ||||
| 		if (retval) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -99,74 +117,18 @@ int read_tree_recursive(struct tree *tree, | |||
| 			int stage, const char **match, | ||||
| 			read_tree_fn_t fn, void *context) | ||||
| { | ||||
| 	struct tree_desc desc; | ||||
| 	struct name_entry entry; | ||||
| 	struct strbuf sb = STRBUF_INIT; | ||||
| 	struct pathspec pathspec; | ||||
| 	int i, ret; | ||||
|  | ||||
| 	if (parse_tree(tree)) | ||||
| 		return -1; | ||||
|  | ||||
| 	init_tree_desc(&desc, tree->buffer, tree->size); | ||||
|  | ||||
| 	while (tree_entry(&desc, &entry)) { | ||||
| 		if (!match_tree_entry(base, baselen, entry.path, entry.mode, match)) | ||||
| 			continue; | ||||
|  | ||||
| 		switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) { | ||||
| 		case 0: | ||||
| 			continue; | ||||
| 		case READ_TREE_RECURSIVE: | ||||
| 			break; | ||||
| 		default: | ||||
| 			return -1; | ||||
| 		} | ||||
| 		if (S_ISDIR(entry.mode)) { | ||||
| 			int retval; | ||||
| 			char *newbase; | ||||
| 			unsigned int pathlen = tree_entry_len(entry.path, entry.sha1); | ||||
|  | ||||
| 			newbase = xmalloc(baselen + 1 + pathlen); | ||||
| 			memcpy(newbase, base, baselen); | ||||
| 			memcpy(newbase + baselen, entry.path, pathlen); | ||||
| 			newbase[baselen + pathlen] = '/'; | ||||
| 			retval = read_tree_recursive(lookup_tree(entry.sha1), | ||||
| 						     newbase, | ||||
| 						     baselen + pathlen + 1, | ||||
| 						     stage, match, fn, context); | ||||
| 			free(newbase); | ||||
| 			if (retval) | ||||
| 				return -1; | ||||
| 			continue; | ||||
| 		} else if (S_ISGITLINK(entry.mode)) { | ||||
| 			int retval; | ||||
| 			struct strbuf path; | ||||
| 			unsigned int entrylen; | ||||
| 			struct commit *commit; | ||||
|  | ||||
| 			entrylen = tree_entry_len(entry.path, entry.sha1); | ||||
| 			strbuf_init(&path, baselen + entrylen + 1); | ||||
| 			strbuf_add(&path, base, baselen); | ||||
| 			strbuf_add(&path, entry.path, entrylen); | ||||
| 			strbuf_addch(&path, '/'); | ||||
|  | ||||
| 			commit = lookup_commit(entry.sha1); | ||||
| 			if (!commit) | ||||
| 				die("Commit %s in submodule path %s not found", | ||||
| 				    sha1_to_hex(entry.sha1), path.buf); | ||||
|  | ||||
| 			if (parse_commit(commit)) | ||||
| 				die("Invalid commit %s in submodule path %s", | ||||
| 				    sha1_to_hex(entry.sha1), path.buf); | ||||
|  | ||||
| 			retval = read_tree_recursive(commit->tree, | ||||
| 						     path.buf, path.len, | ||||
| 						     stage, match, fn, context); | ||||
| 			strbuf_release(&path); | ||||
| 			if (retval) | ||||
| 				return -1; | ||||
| 			continue; | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| 	init_pathspec(&pathspec, match); | ||||
| 	for (i = 0; i < pathspec.nr; i++) | ||||
| 		pathspec.items[i].has_wildcard = 0; | ||||
| 	strbuf_add(&sb, base, baselen); | ||||
| 	ret = read_tree_1(tree, &sb, stage, &pathspec, fn, context); | ||||
| 	strbuf_release(&sb); | ||||
| 	free_pathspec(&pathspec); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int cmp_cache_name_compare(const void *a_, const void *b_) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy