diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2014-07-10 14:10:39 +0200 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2014-10-10 19:35:19 +0200 |
commit | 6843cebe17b7ce15eb9a6d1a88ac2e7e9c00d5b9 (patch) | |
tree | 70d5887084b1ba6e471f9f5723414cd7748575e9 /src/tree-cache.c | |
parent | 19c88310cb79153e19b93c59020b2f7c34794f6e (diff) | |
download | libgit2-6843cebe17b7ce15eb9a6d1a88ac2e7e9c00d5b9.tar.gz |
index: fill the tree cache when reading from a tree
When reading from a tree, we know what every tree is going to look like,
so we can fill in the tree cache completely, making use of the index for
modification of trees a lot quicker.
Diffstat (limited to 'src/tree-cache.c')
-rw-r--r-- | src/tree-cache.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/tree-cache.c b/src/tree-cache.c index d76d9281b..86521ce4d 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -7,6 +7,7 @@ #include "tree-cache.h" #include "pool.h" +#include "tree.h" static git_tree_cache *find_child( const git_tree_cache *tree, const char *path, const char *end) @@ -155,6 +156,76 @@ int git_tree_cache_read(git_tree_cache **tree, const char *buffer, size_t buffer return 0; } +static int read_tree_recursive(git_tree_cache *cache, const git_tree *tree, git_pool *pool) +{ + git_repository *repo; + size_t i, j, nentries, ntrees; + int error; + + repo = git_tree_owner(tree); + + git_oid_cpy(&cache->oid, git_tree_id(tree)); + nentries = git_tree_entrycount(tree); + + /* + * We make sure we know how many trees we need to allocate for + * so we don't have to realloc and change the pointers for the + * parents. + */ + ntrees = 0; + for (i = 0; i < nentries; i++) { + const git_tree_entry *entry; + + entry = git_tree_entry_byindex(tree, i); + if (git_tree_entry_filemode(entry) == GIT_FILEMODE_TREE) + ntrees++; + } + + cache->children_count = ntrees; + cache->children = git_pool_mallocz(pool, ntrees * sizeof(git_tree_cache *)); + GITERR_CHECK_ALLOC(cache->children); + + j = 0; + for (i = 0; i < nentries; i++) { + const git_tree_entry *entry; + git_tree *subtree; + + entry = git_tree_entry_byindex(tree, i); + if (git_tree_entry_filemode(entry) != GIT_FILEMODE_TREE) + continue; + + if ((error = git_tree_cache_new(&cache->children[j], git_tree_entry_name(entry), cache, pool)) < 0) + return error; + + if ((error = git_tree_lookup(&subtree, repo, git_tree_entry_id(entry))) < 0) + return error; + + error = read_tree_recursive(cache->children[j], subtree, pool); + git_tree_free(subtree); + j++; + + if (error < 0) + return error; + } + + return 0; +} + +int git_tree_cache_read_tree(git_tree_cache **out, const git_tree *tree, git_pool *pool) +{ + int error; + git_tree_cache *cache; + + if ((error = git_tree_cache_new(&cache, "", NULL, pool)) < 0) + return error; + + if ((error = read_tree_recursive(cache, tree, pool)) < 0) + return error; + + *out = cache; + return 0; +} + int git_tree_cache_new(git_tree_cache **out, const char *name, git_tree_cache *parent, git_pool *pool) { size_t name_len; |