mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-12 10:05:57 +00:00
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.
This commit is contained in:
parent
19c88310cb
commit
6843cebe17
@ -2277,6 +2277,7 @@ typedef struct read_tree_data {
|
|||||||
git_vector *old_entries;
|
git_vector *old_entries;
|
||||||
git_vector *new_entries;
|
git_vector *new_entries;
|
||||||
git_vector_cmp entry_cmp;
|
git_vector_cmp entry_cmp;
|
||||||
|
git_tree_cache *tree;
|
||||||
} read_tree_data;
|
} read_tree_data;
|
||||||
|
|
||||||
static int read_tree_cb(
|
static int read_tree_cb(
|
||||||
@ -2338,6 +2339,9 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
|
|||||||
data.new_entries = &entries;
|
data.new_entries = &entries;
|
||||||
data.entry_cmp = index->entries_search;
|
data.entry_cmp = index->entries_search;
|
||||||
|
|
||||||
|
index->tree = NULL;
|
||||||
|
git_pool_clear(&index->tree_pool);
|
||||||
|
|
||||||
if (index_sort_if_needed(index, true) < 0)
|
if (index_sort_if_needed(index, true) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -2358,6 +2362,10 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
git_vector_free(&entries);
|
git_vector_free(&entries);
|
||||||
|
if (error < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = git_tree_cache_read_tree(&index->tree, tree, &index->tree_pool);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "tree-cache.h"
|
#include "tree-cache.h"
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
static git_tree_cache *find_child(
|
static git_tree_cache *find_child(
|
||||||
const git_tree_cache *tree, const char *path, const char *end)
|
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;
|
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)
|
int git_tree_cache_new(git_tree_cache **out, const char *name, git_tree_cache *parent, git_pool *pool)
|
||||||
{
|
{
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
|
@ -27,6 +27,10 @@ int git_tree_cache_read(git_tree_cache **tree, const char *buffer, size_t buffer
|
|||||||
void git_tree_cache_invalidate_path(git_tree_cache *tree, const char *path);
|
void git_tree_cache_invalidate_path(git_tree_cache *tree, const char *path);
|
||||||
const git_tree_cache *git_tree_cache_get(const git_tree_cache *tree, const char *path);
|
const git_tree_cache *git_tree_cache_get(const git_tree_cache *tree, const char *path);
|
||||||
int git_tree_cache_new(git_tree_cache **out, const char *name, git_tree_cache *parent, git_pool *pool);
|
int git_tree_cache_new(git_tree_cache **out, const char *name, git_tree_cache *parent, git_pool *pool);
|
||||||
|
/**
|
||||||
|
* Read a tree as the root of the tree cache (like for `git read-tree`)
|
||||||
|
*/
|
||||||
|
int git_tree_cache_read_tree(git_tree_cache **out, const git_tree *tree, git_pool *pool);
|
||||||
void git_tree_cache_free(git_tree_cache *tree);
|
void git_tree_cache_free(git_tree_cache *tree);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user