summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-04-27 08:33:07 (GMT)
committerJunio C Hamano <junkio@cox.net>2006-04-27 08:33:07 (GMT)
commit7927a55d5bde25702dca4fb1a7d6eb7ef61110ba (patch)
treeed3c465e99f20045c9e5e85d4123e2820a097066
parentb34c39cf31e370dad3bcfba29ee8cd023c40fd6b (diff)
downloadgit-7927a55d5bde25702dca4fb1a7d6eb7ef61110ba.zip
git-7927a55d5bde25702dca4fb1a7d6eb7ef61110ba.tar.gz
git-7927a55d5bde25702dca4fb1a7d6eb7ef61110ba.tar.bz2
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>
-rw-r--r--cache-tree.c11
-rw-r--r--cache-tree.h1
-rw-r--r--read-tree.c45
3 files changed, 54 insertions, 3 deletions
diff --git a/cache-tree.c b/cache-tree.c
index d8438d6..35740b3 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -91,6 +91,12 @@ static struct cache_tree_sub *find_subtree(struct cache_tree *it,
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)
{
/* 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 *subtree;
const char *name = buf;
- int namelen;
+
sub = read_one(&buf, &size);
if (!sub)
goto free_return;
- namelen = strlen(name);
- subtree = find_subtree(it, name, namelen, 1);
+ subtree = cache_tree_sub(it, name);
subtree->cache_tree = sub;
}
if (subtree_nr != it->subtree_nr)
diff --git a/cache-tree.h b/cache-tree.h
index c70a769..5d824df 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -20,6 +20,7 @@ struct cache_tree {
struct cache_tree *cache_tree(void);
void cache_tree_free(struct cache_tree **);
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);
struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
diff --git a/read-tree.c b/read-tree.c
index ab51682..66c0120 100644
--- a/read-tree.c
+++ b/read-tree.c
@@ -725,6 +725,39 @@ static int read_cache_unmerged(void)
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 struct cache_file cache_file;
@@ -839,6 +872,18 @@ int main(int argc, char **argv)
}
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) ||
commit_index_file(&cache_file))
die("unable to write new index file");