diff --git a/include/git2/tree.h b/include/git2/tree.h index f12b15e2e..5c42f3957 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -128,6 +128,17 @@ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byname(git_tree *tree, const c */ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(git_tree *tree, unsigned int idx); +/** + * Lookup a tree entry by SHA value. + * + * Warning: this must examine every entry in the tree, so it is not fast. + * + * @param tree a previously loaded tree. + * @param oid the sha being looked for + * @return the tree entry; NULL if not found + */ +GIT_EXTERN(const git_tree_entry *) git_tree_entry_byoid(git_tree *tree, const git_oid *oid); + /** * Get the UNIX file attributes of a tree entry * diff --git a/src/tree.c b/src/tree.c index 9d793cbb8..422e62b28 100644 --- a/src/tree.c +++ b/src/tree.c @@ -240,6 +240,21 @@ const git_tree_entry *git_tree_entry_byindex(git_tree *tree, unsigned int idx) return git_vector_get(&tree->entries, idx); } +const git_tree_entry *git_tree_entry_byoid(git_tree *tree, const git_oid *oid) +{ + unsigned int i; + git_tree_entry *e; + + assert(tree); + + git_vector_foreach(&tree->entries, i, e) { + if (memcmp(&e->oid.id, &oid->id, sizeof(oid->id)) == 0) + return e; + } + + return NULL; +} + int git_tree__prefix_position(git_tree *tree, const char *path) { git_vector *entries = &tree->entries; @@ -724,7 +739,7 @@ int git_tree_entry_bypath( } switch (path[filename_len]) { - case '/': + case '/': /* If there are more components in the path... * then this entry *must* be a tree */ if (!git_tree_entry__is_tree(entry)) { @@ -772,8 +787,9 @@ static int tree_walk( for (i = 0; i < tree->entries.length; ++i) { git_tree_entry *entry = tree->entries.contents[i]; - if (preorder && callback(path->ptr, entry, payload) < 0) - return -1; + if (preorder && + (error = callback(path->ptr, entry, payload)) != 0) + break; if (git_tree_entry__is_tree(entry)) { git_tree *subtree; @@ -790,18 +806,20 @@ static int tree_walk( if (git_buf_oom(path)) return -1; - if (tree_walk(subtree, callback, path, payload, preorder) < 0) - return -1; + error = tree_walk(subtree, callback, path, payload, preorder); + if (error != 0) + break; git_buf_truncate(path, path_len); git_tree_free(subtree); } - if (!preorder && callback(path->ptr, entry, payload) < 0) - return -1; + if (!preorder && + (error = callback(path->ptr, entry, payload)) != 0) + break; } - return 0; + return error; } int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode, void *payload)