read-tree: teach 1-way merege and plain read to prime cache-tree.

This teaches read-tree to fully populate valid cache-tree when
reading a tree from scratch, or reading a single tree into an
existing index, reusing only the cached stat information (i.e.
one-way merge).  We have already taught update-index about cache-tree,
so "git checkout" followed by updates to a few path followed by
a "git commit" would become very efficient.

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2006-04-27 01:33:07 -07:00
parent b34c39cf31
commit 7927a55d5b
3 changed files with 54 additions and 3 deletions

View File

@ -91,6 +91,12 @@ static struct cache_tree_sub *find_subtree(struct cache_tree *it,
return down; return down;
} }
struct cache_tree_sub *cache_tree_sub(struct cache_tree *it, const char *path)
{
int pathlen = strlen(path);
return find_subtree(it, path, pathlen, 1);
}
void cache_tree_invalidate_path(struct cache_tree *it, const char *path) void cache_tree_invalidate_path(struct cache_tree *it, const char *path)
{ {
/* a/b/c /* a/b/c
@ -476,12 +482,11 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
struct cache_tree *sub; struct cache_tree *sub;
struct cache_tree_sub *subtree; struct cache_tree_sub *subtree;
const char *name = buf; const char *name = buf;
int namelen;
sub = read_one(&buf, &size); sub = read_one(&buf, &size);
if (!sub) if (!sub)
goto free_return; goto free_return;
namelen = strlen(name); subtree = cache_tree_sub(it, name);
subtree = find_subtree(it, name, namelen, 1);
subtree->cache_tree = sub; subtree->cache_tree = sub;
} }
if (subtree_nr != it->subtree_nr) if (subtree_nr != it->subtree_nr)

View File

@ -20,6 +20,7 @@ struct cache_tree {
struct cache_tree *cache_tree(void); struct cache_tree *cache_tree(void);
void cache_tree_free(struct cache_tree **); void cache_tree_free(struct cache_tree **);
void cache_tree_invalidate_path(struct cache_tree *, const char *); void cache_tree_invalidate_path(struct cache_tree *, const char *);
struct cache_tree_sub *cache_tree_sub(struct cache_tree *, const char *);
void *cache_tree_write(struct cache_tree *root, unsigned long *size_p); void *cache_tree_write(struct cache_tree *root, unsigned long *size_p);
struct cache_tree *cache_tree_read(const char *buffer, unsigned long size); struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);

View File

@ -725,6 +725,39 @@ static int read_cache_unmerged(void)
return deleted; return deleted;
} }
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
{
struct tree_entry_list *ent;
int cnt;
memcpy(it->sha1, tree->object.sha1, 20);
for (cnt = 0, ent = tree->entries; ent; ent = ent->next) {
if (!ent->directory)
cnt++;
else {
struct cache_tree_sub *sub;
struct tree *subtree = (struct tree *)ent->item.tree;
if (!subtree->object.parsed)
parse_tree(subtree);
sub = cache_tree_sub(it, ent->name);
sub->cache_tree = cache_tree();
prime_cache_tree_rec(sub->cache_tree, subtree);
cnt += sub->cache_tree->entry_count;
}
}
it->entry_count = cnt;
}
static void prime_cache_tree(void)
{
struct tree *tree = (struct tree *)trees->item;
if (!tree)
return;
active_cache_tree = cache_tree();
prime_cache_tree_rec(active_cache_tree, tree);
}
static const char read_tree_usage[] = "git-read-tree (<sha> | -m [--aggressive] [-u | -i] <sha1> [<sha2> [<sha3>]])"; static const char read_tree_usage[] = "git-read-tree (<sha> | -m [--aggressive] [-u | -i] <sha1> [<sha2> [<sha3>]])";
static struct cache_file cache_file; static struct cache_file cache_file;
@ -839,6 +872,18 @@ int main(int argc, char **argv)
} }
unpack_trees(fn); unpack_trees(fn);
/*
* When reading only one tree (either the most basic form,
* "-m ent" or "--reset ent" form), we can obtain a fully
* valid cache-tree because the index must match exactly
* what came from the tree.
*/
if (trees->item && (!merge || (stage == 2))) {
cache_tree_free(&active_cache_tree);
prime_cache_tree();
}
if (write_cache(newfd, active_cache, active_nr) || if (write_cache(newfd, active_cache, active_nr) ||
commit_index_file(&cache_file)) commit_index_file(&cache_file))
die("unable to write new index file"); die("unable to write new index file");