cache-tree: create/update cache-tree on checkout
authorDavid Turner <dturner@twopensource.com>
Sun, 6 Jul 2014 04:06:56 +0000 (21:06 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Jul 2014 19:30:34 +0000 (12:30 -0700)
When git checkout checks out a branch, create or update the
cache-tree so that subsequent operations are faster.

update_main_cache_tree learned a new flag, WRITE_TREE_REPAIR. When
WRITE_TREE_REPAIR is set, portions of the cache-tree which do not
correspond to existing tree objects are invalidated (and portions which
do are marked as valid). No new tree objects are created.

Signed-off-by: David Turner <dturner@twitter.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/checkout.c
cache-tree.c
cache-tree.h
t/t0090-cache-tree.sh
index 07cf55530918e8de6ae45e1c9b7e16707c32f844..054214fe43c8f8e3b815d4afb747408f2524c378 100644 (file)
@@ -553,6 +553,14 @@ static int merge_working_tree(const struct checkout_opts *opts,
                }
        }
 
+       if (!active_cache_tree)
+               active_cache_tree = cache_tree();
+
+       if (!cache_tree_fully_valid(active_cache_tree))
+               cache_tree_update(active_cache_tree,
+                                 (const struct cache_entry * const *)active_cache,
+                                 active_nr, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
+
        if (write_cache(newfd, active_cache, active_nr) ||
            commit_locked_index(lock_file))
                die(_("unable to write new index file"));
index 7fa524a11323621d24c352b0a1108ae953a60cf5..f951d7d3c4d8ec8f67c896d835cef16b74c6f171 100644 (file)
@@ -239,9 +239,12 @@ static int update_one(struct cache_tree *it,
        struct strbuf buffer;
        int missing_ok = flags & WRITE_TREE_MISSING_OK;
        int dryrun = flags & WRITE_TREE_DRY_RUN;
+       int repair = flags & WRITE_TREE_REPAIR;
        int to_invalidate = 0;
        int i;
 
+       assert(!(dryrun && repair));
+
        *skip_count = 0;
 
        if (0 <= it->entry_count && has_sha1_file(it->sha1))
@@ -374,7 +377,14 @@ static int update_one(struct cache_tree *it,
 #endif
        }
 
-       if (dryrun)
+       if (repair) {
+               unsigned char sha1[20];
+               hash_sha1_file(buffer.buf, buffer.len, tree_type, sha1);
+               if (has_sha1_file(sha1))
+                       hashcpy(it->sha1, sha1);
+               else
+                       to_invalidate = 1;
+       } else if (dryrun)
                hash_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1);
        else if (write_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1)) {
                strbuf_release(&buffer);
index f1923ad1e9ddd3ad9b77a436e66ad083843094a0..666d18f8348ba4a6d25e8d1a301b2e1fac0ebaaf 100644 (file)
@@ -39,6 +39,7 @@ int update_main_cache_tree(int);
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
 #define WRITE_TREE_DRY_RUN 4
 #define WRITE_TREE_SILENT 8
+#define WRITE_TREE_REPAIR 16
 
 /* error return codes */
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
index 6c33e28ee8df4d239dd6d1c1d98c324b01c70ed3..98fb1ab6daab92ffd54f7ce82bccd4d10896def9 100755 (executable)
@@ -44,14 +44,14 @@ test_expect_success 'read-tree HEAD establishes cache-tree' '
 
 test_expect_success 'git-add invalidates cache-tree' '
        test_when_finished "git reset --hard; git read-tree HEAD" &&
-       echo "I changed this file" > foo &&
+       echo "I changed this file" >foo &&
        git add foo &&
        test_invalid_cache_tree
 '
 
 test_expect_success 'update-index invalidates cache-tree' '
        test_when_finished "git reset --hard; git read-tree HEAD" &&
-       echo "I changed this file" > foo &&
+       echo "I changed this file" >foo &&
        git update-index --add foo &&
        test_invalid_cache_tree
 '
@@ -85,9 +85,22 @@ test_expect_success 'reset --hard without index gives cache-tree' '
        test_shallow_cache_tree
 '
 
-test_expect_failure 'checkout gives cache-tree' '
+test_expect_success 'checkout gives cache-tree' '
+       git tag current &&
        git checkout HEAD^ &&
        test_shallow_cache_tree
 '
 
+test_expect_success 'checkout -b gives cache-tree' '
+       git checkout current &&
+       git checkout -b prev HEAD^ &&
+       test_shallow_cache_tree
+'
+
+test_expect_success 'checkout -B gives cache-tree' '
+       git checkout current &&
+       git checkout -B prev HEAD^ &&
+       test_shallow_cache_tree
+'
+
 test_done