read-tree: teach 1-way merege and plain read to prime cache-tree.
authorJunio C Hamano <junkio@cox.net>
Thu, 27 Apr 2006 08:33:07 +0000 (01:33 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 27 Apr 2006 08:33:07 +0000 (01:33 -0700)
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>
cache-tree.c
cache-tree.h
read-tree.c
index d8438d67d7ce5549c0b2baa377bec31202619138..35740b3647018b0dae7d38cab730b7d4d7213753 100644 (file)
@@ -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)
index c70a7699a9f13da74304a3f882daf2d810ff5398..5d824df2ec3d94124fe3da3be43bcfbac871cdb8 100644 (file)
@@ -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);
index ab516824ef92cd66146ca3d453f3461119e41155..66c0120f1352f8edf6ea1afcd037c96b373273a8 100644 (file)
@@ -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");