Commit 8cf2de078def3820a3a3208496ba705df28aad15

Vicent Marti 2011-10-19T01:34:42

tree: Fix lookups by entry name

diff --git a/include/git2/tree.h b/include/git2/tree.h
index 8d638f7..e305950 100644
--- a/include/git2/tree.h
+++ b/include/git2/tree.h
@@ -88,6 +88,9 @@ GIT_EXTERN(unsigned int) git_tree_entrycount(git_tree *tree);
 /**
  * Lookup a tree entry by its filename
  *
+ * Note that if the entry in the tree is a folder instead of
+ * a standard file, the given name must be ended with a slash.
+ *
  * @param tree a previously loaded tree.
  * @param filename the filename of the desired entry
  * @return the tree entry; NULL if not found
@@ -203,6 +206,9 @@ GIT_EXTERN(void) git_treebuilder_free(git_treebuilder *bld);
 /**
  * Get an entry from the builder from its filename
  *
+ * Note that if the entry in the tree is a folder instead of
+ * a standard file, the given name must be ended with a slash.
+ *
  * The returned entry is owned by the builder and should
  * not be freed manually.
  *
diff --git a/src/tree.c b/src/tree.c
index 3801df1..27c018f 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -23,6 +23,7 @@ static int valid_attributes(const int attributes)
 struct tree_key_search {
 	const char *filename;
 	size_t filename_len;
+	int is_folder;
 };
 
 static int entry_search_cmp(const void *key, const void *array_member)
@@ -32,7 +33,7 @@ static int entry_search_cmp(const void *key, const void *array_member)
 
 	int result =
 		git_futils_cmp_path(
-			ksearch->filename, ksearch->filename_len, entry->attr & 040000,
+			ksearch->filename, ksearch->filename_len, ksearch->is_folder,
 			entry->filename, entry->filename_len, entry->attr & 040000);
 
 	return result ? result : ((int)ksearch->filename_len - (int)entry->filename_len);
@@ -51,15 +52,19 @@ static int entry_sort_cmp(const void *a, const void *b)
 static int build_ksearch(struct tree_key_search *ksearch, const char *path)
 {
 	size_t len = strlen(path);
+	int is_folder = 0;
 
-	if (len && path[len - 1] == '/')
+	if (len && path[len - 1] == '/') {
+		is_folder = 1;
 		len--;
+	}
 
 	if (len == 0 || memchr(path, '/', len) != NULL)
 		return GIT_ERROR;
 
 	ksearch->filename = path;
 	ksearch->filename_len = len;
+	ksearch->is_folder = is_folder;
 
 	return GIT_SUCCESS;
 }
@@ -420,6 +425,10 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
 	if (build_ksearch(&ksearch, filename) < GIT_SUCCESS)
 		return git__throw(GIT_ERROR, "Failed to insert entry. Invalid filename '%s'", filename);
 
+	if ((attributes & 040000) != 0) {
+		ksearch.is_folder = 1;
+	}
+
 	if ((pos = git_vector_bsearch2(&bld->entries, entry_search_cmp, &ksearch)) != GIT_ENOTFOUND) {
 		entry = git_vector_get(&bld->entries, pos);
 		if (entry->removed) {