cache-tree: Write updated cache-tree after commit

During the commit process, update the cache-tree. Write this updated cache-tree so that it's ready for subsequent commands. Add test code which demonstrates that git commit now writes the cache tree. Make all tests test the entire cache-tree, not just the root level. Signed-off-by: David Turner <dturner@twitter.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Turner committed Jul 13, 2014 at 13:28 UTC 9c4d6c0297b7d6167bf330853139b0515b351b89
2 files changed +119 -16
builtin/commit.c
+17 -1
@@ -342,6 +342,17 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
342
343 discard_cache();
344 read_cache_from(index_lock.filename);
345 + if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
346 + fd = open(index_lock.filename, O_WRONLY);
347 + if (fd >= 0)
348 + if (write_cache(fd, active_cache, active_nr) < 0)
349 + die(_("unable to write index file"));
350 + else
351 + close_lock_file(&index_lock);
352 + else
353 + die(_("unable to write index file"));
354 + } else
355 + warning(_("Failed to update main cache tree"));
356
357 commit_style = COMMIT_NORMAL;
358 return index_lock.filename;
@@ -383,8 +394,12 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
394 if (!only && !pathspec.nr) {
395 fd = hold_locked_index(&index_lock, 1);
396 refresh_cache_or_die(refresh_flags);
386 - if (active_cache_changed) {
397 + if (active_cache_changed
398 + || !cache_tree_fully_valid(active_cache_tree)) {
399 update_main_cache_tree(WRITE_TREE_SILENT);
400 + active_cache_changed = 1;
401 + }
402 + if (active_cache_changed) {
403 if (write_cache(fd, active_cache, active_nr) ||
404 commit_locked_index(&index_lock))
405 die(_("unable to write new_index file"));
@@ -435,6 +450,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
450 fd = hold_locked_index(&index_lock, 1);
451 add_remove_files(&partial);
452 refresh_cache(REFRESH_QUIET);
453 + update_main_cache_tree(WRITE_TREE_SILENT);
454 if (write_cache(fd, active_cache, active_nr) ||
455 close_lock_file(&index_lock))
456 die(_("unable to write new_index file"));
t/t0090-cache-tree.sh
+102 -15
@@ -8,7 +8,7 @@ cache-tree extension.
8 . ./test-lib.sh
9
10 cmp_cache_tree () {
11 - test-dump-cache-tree >actual &&
11 + test-dump-cache-tree | sed -e '/#(ref)/d' >actual &&
12 sed "s/$_x40/SHA/" <actual >filtered &&
13 test_cmp "$1" filtered
14 }
@@ -16,14 +16,38 @@ cmp_cache_tree () {
16 # We don't bother with actually checking the SHA1:
17 # test-dump-cache-tree already verifies that all existing data is
18 # correct.
19 -test_shallow_cache_tree () {
20 - printf "SHA (%d entries, 0 subtrees)\n" $(git ls-files|wc -l) >expect &&
19 +generate_expected_cache_tree_rec () {
20 + dir="$1${1:+/}" &&
21 + parent="$2" &&
22 + # ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux
23 + # We want to count only foo because it's the only direct child
24 + subtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&
25 + subtree_count=$(echo "$subtrees"|awk '$1 {++c} END {print c}') &&
26 + entries=$(git ls-files|wc -l) &&
27 + printf "SHA $dir (%d entries, %d subtrees)\n" "$entries" "$subtree_count" &&
28 + for subtree in $subtrees
29 + do
30 + cd "$subtree"
31 + generate_expected_cache_tree_rec "$dir$subtree" "$dir" || return 1
32 + cd ..
33 + done &&
34 + dir=$parent
35 +}
36 +
37 +generate_expected_cache_tree () {
38 + (
39 + generate_expected_cache_tree_rec
40 + )
41 +}
42 +
43 +test_cache_tree () {
44 + generate_expected_cache_tree >expect &&
45 cmp_cache_tree expect
46 }
47
48 test_invalid_cache_tree () {
49 printf "invalid %s ()\n" "" "$@" >expect &&
26 - test-dump-cache-tree | \
50 + test-dump-cache-tree |
51 sed -n -e "s/[0-9]* subtrees//" -e '/#(ref)/d' -e '/^invalid /p' >actual &&
52 test_cmp expect actual
53 }
@@ -33,14 +57,14 @@ test_no_cache_tree () {
57 cmp_cache_tree expect
58 }
59
36 -test_expect_failure 'initial commit has cache-tree' '
60 +test_expect_success 'initial commit has cache-tree' '
61 test_commit foo &&
38 - test_shallow_cache_tree
62 + test_cache_tree
63 '
64
65 test_expect_success 'read-tree HEAD establishes cache-tree' '
66 git read-tree HEAD &&
43 - test_shallow_cache_tree
67 + test_cache_tree
68 '
69
70 test_expect_success 'git-add invalidates cache-tree' '
@@ -58,6 +82,18 @@ test_expect_success 'git-add in subdir invalidates cache-tree' '
82 test_invalid_cache_tree
83 '
84
85 +cat >before <<\EOF
86 +SHA (3 entries, 2 subtrees)
87 +SHA dir1/ (1 entries, 0 subtrees)
88 +SHA dir2/ (1 entries, 0 subtrees)
89 +EOF
90 +
91 +cat >expect <<\EOF
92 +invalid (2 subtrees)
93 +invalid dir1/ (0 subtrees)
94 +SHA dir2/ (1 entries, 0 subtrees)
95 +EOF
96 +
97 test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '
98 git tag no-children &&
99 test_when_finished "git reset --hard no-children; git read-tree HEAD" &&
@@ -65,8 +101,10 @@ test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '
101 test_commit dir1/a &&
102 test_commit dir2/b &&
103 echo "I changed this file" >dir1/a &&
104 + cmp_cache_tree before &&
105 + echo "I changed this file" >dir1/a &&
106 git add dir1/a &&
69 - test_invalid_cache_tree dir1/
107 + cmp_cache_tree expect
108 '
109
110 test_expect_success 'update-index invalidates cache-tree' '
@@ -79,7 +117,7 @@ test_expect_success 'update-index invalidates cache-tree' '
117 test_expect_success 'write-tree establishes cache-tree' '
118 test-scrap-cache-tree &&
119 git write-tree &&
82 - test_shallow_cache_tree
120 + test_cache_tree
121 '
122
123 test_expect_success 'test-scrap-cache-tree works' '
@@ -90,37 +128,86 @@ test_expect_success 'test-scrap-cache-tree works' '
128
129 test_expect_success 'second commit has cache-tree' '
130 test_commit bar &&
93 - test_shallow_cache_tree
131 + test_cache_tree
132 +'
133 +
134 +test_expect_success 'commit --interactive gives cache-tree on partial commit' '
135 + cat <<-\EOT >foo.c &&
136 + int foo()
137 + {
138 + return 42;
139 + }
140 + int bar()
141 + {
142 + return 42;
143 + }
144 + EOT
145 + git add foo.c &&
146 + test_invalid_cache_tree &&
147 + git commit -m "add a file" &&
148 + test_cache_tree &&
149 + cat <<-\EOT >foo.c &&
150 + int foo()
151 + {
152 + return 43;
153 + }
154 + int bar()
155 + {
156 + return 44;
157 + }
158 + EOT
159 + (echo p; echo 1; echo; echo s; echo n; echo y; echo q) |
160 + git commit --interactive -m foo &&
161 + test_cache_tree
162 +'
163 +
164 +test_expect_success 'commit in child dir has cache-tree' '
165 + mkdir dir &&
166 + >dir/child.t &&
167 + git add dir/child.t &&
168 + git commit -m dir/child.t &&
169 + test_cache_tree
170 '
171
172 test_expect_success 'reset --hard gives cache-tree' '
173 test-scrap-cache-tree &&
174 git reset --hard &&
99 - test_shallow_cache_tree
175 + test_cache_tree
176 '
177
178 test_expect_success 'reset --hard without index gives cache-tree' '
179 rm -f .git/index &&
180 git reset --hard &&
105 - test_shallow_cache_tree
181 + test_cache_tree
182 '
183
184 test_expect_success 'checkout gives cache-tree' '
185 git tag current &&
186 git checkout HEAD^ &&
111 - test_shallow_cache_tree
187 + test_cache_tree
188 '
189
190 test_expect_success 'checkout -b gives cache-tree' '
191 git checkout current &&
192 git checkout -b prev HEAD^ &&
117 - test_shallow_cache_tree
193 + test_cache_tree
194 '
195
196 test_expect_success 'checkout -B gives cache-tree' '
197 git checkout current &&
198 git checkout -B prev HEAD^ &&
123 - test_shallow_cache_tree
199 + test_cache_tree
200 +'
201 +
202 +test_expect_success 'partial commit gives cache-tree' '
203 + git checkout -b partial no-children &&
204 + test_commit one &&
205 + test_commit two &&
206 + echo "some change" >one.t &&
207 + git add one.t &&
208 + echo "some other change" >two.t &&
209 + git commit two.t -m partial &&
210 + test_cache_tree
211 '
212
213 test_done