3 test_description='split commit graph'
6 GIT_TEST_COMMIT_GRAPH=0
7 GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0
9 test_expect_success 'setup repo' '
11 git config core.commitGraph true &&
12 git config gc.writeCommitGraph false &&
13 infodir=".git/objects/info" &&
14 graphdir="$infodir/commit-graphs" &&
31 header: 43475048 1 1 3 $NUM_BASE
33 chunks: oid_fanout oid_lookup commit_metadata
35 test-tool read-graph >output &&
36 test_cmp expect output
39 test_expect_success POSIXPERM 'tweak umask for modebit tests' '
43 test_expect_success 'create commits and write commit-graph' '
44 for i in $(test_seq 3)
47 git branch commits/$i || return 1
49 git commit-graph write --reachable &&
50 test_path_is_file $infodir/commit-graph &&
54 graph_git_two_modes() {
55 git -c core.commitGraph=true $1 >output
56 git -c core.commitGraph=false $1 >expect
57 test_cmp expect output
60 graph_git_behavior() {
64 test_expect_success "check normal git operations: $MSG" '
65 graph_git_two_modes "log --oneline $BRANCH" &&
66 graph_git_two_modes "log --topo-order $BRANCH" &&
67 graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
68 graph_git_two_modes "branch -vv" &&
69 graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
73 graph_git_behavior 'graph exists' commits/3 commits/1
75 verify_chain_files_exist() {
76 for hash in $(cat $1/commit-graph-chain)
78 test_path_is_file $1/graph-$hash.graph || return 1
82 test_expect_success 'add more commits, and write a new base graph' '
83 git reset --hard commits/1 &&
84 for i in $(test_seq 4 5)
87 git branch commits/$i || return 1
89 git reset --hard commits/2 &&
90 for i in $(test_seq 6 10)
93 git branch commits/$i || return 1
95 git reset --hard commits/2 &&
96 git merge commits/4 &&
98 git reset --hard commits/4 &&
99 git merge commits/6 &&
100 git branch merge/2 &&
101 git commit-graph write --reachable &&
105 test_expect_success 'fork and fail to base a chain on a commit-graph file' '
106 test_when_finished rm -rf fork &&
110 rm .git/objects/info/commit-graph &&
111 echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
112 test_commit new-commit &&
113 git commit-graph write --reachable --split &&
114 test_path_is_file $graphdir/commit-graph-chain &&
115 test_line_count = 1 $graphdir/commit-graph-chain &&
116 verify_chain_files_exist $graphdir
120 test_expect_success 'add three more commits, write a tip graph' '
121 git reset --hard commits/3 &&
123 git merge commits/5 &&
125 git branch merge/3 &&
126 git commit-graph write --reachable --split &&
127 test_path_is_missing $infodir/commit-graph &&
128 test_path_is_file $graphdir/commit-graph-chain &&
129 ls $graphdir/graph-*.graph >graph-files &&
130 test_line_count = 2 graph-files &&
131 verify_chain_files_exist $graphdir
134 graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2
136 test_expect_success 'add one commit, write a tip graph' '
138 git branch commits/11 &&
139 git commit-graph write --reachable --split &&
140 test_path_is_missing $infodir/commit-graph &&
141 test_path_is_file $graphdir/commit-graph-chain &&
142 ls $graphdir/graph-*.graph >graph-files &&
143 test_line_count = 3 graph-files &&
144 verify_chain_files_exist $graphdir
147 graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits/6
149 test_expect_success 'add one commit, write a merged graph' '
151 git branch commits/12 &&
152 git commit-graph write --reachable --split &&
153 test_path_is_file $graphdir/commit-graph-chain &&
154 test_line_count = 2 $graphdir/commit-graph-chain &&
155 ls $graphdir/graph-*.graph >graph-files &&
156 test_line_count = 2 graph-files &&
157 verify_chain_files_exist $graphdir
160 graph_git_behavior 'merged commit-graph: commit 12 vs 6' commits/12 commits/6
162 test_expect_success 'create fork and chain across alternate' '
166 git config core.commitGraph true &&
168 echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
170 git branch commits/13 &&
171 git commit-graph write --reachable --split &&
172 test_path_is_file $graphdir/commit-graph-chain &&
173 test_line_count = 3 $graphdir/commit-graph-chain &&
174 ls $graphdir/graph-*.graph >graph-files &&
175 test_line_count = 1 graph-files &&
176 git -c core.commitGraph=true rev-list HEAD >expect &&
177 git -c core.commitGraph=false rev-list HEAD >actual &&
178 test_cmp expect actual &&
180 git commit-graph write --reachable --split --object-dir=.git/objects/ &&
181 test_line_count = 3 $graphdir/commit-graph-chain &&
182 ls $graphdir/graph-*.graph >graph-files &&
183 test_line_count = 1 graph-files
187 graph_git_behavior 'alternate: commit 13 vs 6' commits/13 commits/6
189 test_expect_success 'test merge stragety constants' '
190 git clone . merge-2 &&
193 git config core.commitGraph true &&
194 test_line_count = 2 $graphdir/commit-graph-chain &&
196 git commit-graph write --reachable --split --size-multiple=2 &&
197 test_line_count = 3 $graphdir/commit-graph-chain
200 git clone . merge-10 &&
203 git config core.commitGraph true &&
204 test_line_count = 2 $graphdir/commit-graph-chain &&
206 git commit-graph write --reachable --split --size-multiple=10 &&
207 test_line_count = 1 $graphdir/commit-graph-chain &&
208 ls $graphdir/graph-*.graph >graph-files &&
209 test_line_count = 1 graph-files
211 git clone . merge-10-expire &&
213 cd merge-10-expire &&
214 git config core.commitGraph true &&
215 test_line_count = 2 $graphdir/commit-graph-chain &&
217 touch $graphdir/to-delete.graph $graphdir/to-keep.graph &&
218 test-tool chmtime =1546362000 $graphdir/to-delete.graph &&
219 test-tool chmtime =1546362001 $graphdir/to-keep.graph &&
220 git commit-graph write --reachable --split --size-multiple=10 \
221 --expire-time="2019-01-01 12:00 -05:00" &&
222 test_line_count = 1 $graphdir/commit-graph-chain &&
223 test_path_is_missing $graphdir/to-delete.graph &&
224 test_path_is_file $graphdir/to-keep.graph &&
225 ls $graphdir/graph-*.graph >graph-files &&
226 test_line_count = 3 graph-files
228 git clone --no-hardlinks . max-commits &&
231 git config core.commitGraph true &&
232 test_line_count = 2 $graphdir/commit-graph-chain &&
235 git commit-graph write --reachable --split --max-commits=1 &&
236 test_line_count = 1 $graphdir/commit-graph-chain &&
237 ls $graphdir/graph-*.graph >graph-files &&
238 test_line_count = 1 graph-files
242 test_expect_success 'remove commit-graph-chain file after flattening' '
243 git clone . flatten &&
246 test_line_count = 2 $graphdir/commit-graph-chain &&
247 git commit-graph write --reachable &&
248 test_path_is_missing $graphdir/commit-graph-chain &&
249 ls $graphdir >graph-files &&
250 test_line_count = 0 graph-files
259 printf "$data" | dd of="$file" bs=1 seek="$pos" conv=notrunc
262 test_expect_success 'verify hashes along chain, even in shallow' '
263 git clone --no-hardlinks . verify &&
266 git commit-graph verify &&
267 base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
268 corrupt_file "$base_file" $(test_oid shallow) "\01" &&
269 test_must_fail git commit-graph verify --shallow 2>test_err &&
270 grep -v "^+" test_err >err &&
271 test_i18ngrep "incorrect checksum" err
275 test_expect_success 'verify --shallow does not check base contents' '
276 git clone --no-hardlinks . verify-shallow &&
279 git commit-graph verify &&
280 base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
281 corrupt_file "$base_file" 1000 "\01" &&
282 git commit-graph verify --shallow &&
283 test_must_fail git commit-graph verify 2>test_err &&
284 grep -v "^+" test_err >err &&
285 test_i18ngrep "incorrect checksum" err
289 test_expect_success 'warn on base graph chunk incorrect' '
290 git clone --no-hardlinks . base-chunk &&
293 git commit-graph verify &&
294 base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
295 corrupt_file "$base_file" $(test_oid base) "\01" &&
296 git commit-graph verify --shallow 2>test_err &&
297 grep -v "^+" test_err >err &&
298 test_i18ngrep "commit-graph chain does not match" err
302 test_expect_success 'verify after commit-graph-chain corruption' '
303 git clone --no-hardlinks . verify-chain &&
306 corrupt_file "$graphdir/commit-graph-chain" 60 "G" &&
307 git commit-graph verify 2>test_err &&
308 grep -v "^+" test_err >err &&
309 test_i18ngrep "invalid commit-graph chain" err &&
310 corrupt_file "$graphdir/commit-graph-chain" 60 "A" &&
311 git commit-graph verify 2>test_err &&
312 grep -v "^+" test_err >err &&
313 test_i18ngrep "unable to find all commit-graph files" err
317 test_expect_success 'verify across alternates' '
318 git clone --no-hardlinks . verify-alt &&
322 altdir="$(pwd)/../.git/objects" &&
323 echo "$altdir" >.git/objects/info/alternates &&
324 git commit-graph verify --object-dir="$altdir/" &&
326 git commit-graph write --reachable --split &&
327 tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
328 corrupt_file "$tip_file" 100 "\01" &&
329 test_must_fail git commit-graph verify --shallow 2>test_err &&
330 grep -v "^+" test_err >err &&
331 test_i18ngrep "commit-graph has incorrect fanout value" err
335 test_expect_success 'add octopus merge' '
336 git reset --hard commits/10 &&
337 git merge commits/3 commits/4 &&
338 git branch merge/octopus &&
339 git commit-graph write --reachable --split &&
340 git commit-graph verify --progress 2>err &&
341 test_line_count = 3 err &&
342 test_i18ngrep ! warning err &&
343 test_line_count = 3 $graphdir/commit-graph-chain
346 graph_git_behavior 'graph exists' merge/octopus commits/12
348 test_expect_success 'split across alternate where alternate is not split' '
349 git commit-graph write --reachable &&
350 test_path_is_file .git/objects/info/commit-graph &&
351 cp .git/objects/info/commit-graph . &&
352 git clone --no-hardlinks . alt-split &&
355 rm -f .git/objects/info/commit-graph &&
356 echo "$(pwd)"/../.git/objects >.git/objects/info/alternates &&
358 git commit-graph write --reachable --split &&
359 test_line_count = 1 $graphdir/commit-graph-chain
361 test_cmp commit-graph .git/objects/info/commit-graph
364 test_expect_success '--split=no-merge always writes an incremental' '
365 test_when_finished rm -rf a b &&
366 rm -rf $graphdir $infodir/commit-graph &&
367 git reset --hard commits/2 &&
368 git rev-list HEAD~1 >a &&
369 git rev-list HEAD >b &&
370 git commit-graph write --split --stdin-commits <a &&
371 git commit-graph write --split=no-merge --stdin-commits <b &&
372 test_line_count = 2 $graphdir/commit-graph-chain
375 test_expect_success '--split=replace replaces the chain' '
376 rm -rf $graphdir $infodir/commit-graph &&
377 git reset --hard commits/3 &&
378 git rev-list -1 HEAD~2 >a &&
379 git rev-list -1 HEAD~1 >b &&
380 git rev-list -1 HEAD >c &&
381 git commit-graph write --split=no-merge --stdin-commits <a &&
382 git commit-graph write --split=no-merge --stdin-commits <b &&
383 git commit-graph write --split=no-merge --stdin-commits <c &&
384 test_line_count = 3 $graphdir/commit-graph-chain &&
385 git commit-graph write --stdin-commits --split=replace <b &&
386 test_path_is_missing $infodir/commit-graph &&
387 test_path_is_file $graphdir/commit-graph-chain &&
388 ls $graphdir/graph-*.graph >graph-files &&
389 test_line_count = 1 graph-files &&
390 verify_chain_files_exist $graphdir &&
394 test_expect_success ULIMIT_FILE_DESCRIPTORS 'handles file descriptor exhaustion' '
398 for i in $(test_seq 64)
401 run_with_limited_open_files test_might_fail git commit-graph write \
402 --split=no-merge --reachable || return 1
407 while read mode modebits
409 test_expect_success POSIXPERM "split commit-graph respects core.sharedrepository $mode" '
410 rm -rf $graphdir $infodir/commit-graph &&
411 git reset --hard commits/1 &&
412 test_config core.sharedrepository "$mode" &&
413 git commit-graph write --split --reachable &&
414 ls $graphdir/graph-*.graph >graph-files &&
415 test_line_count = 1 graph-files &&
416 echo "$modebits" >expect &&
417 test_modebits $graphdir/graph-*.graph >actual &&
418 test_cmp expect actual &&
419 test_modebits $graphdir/commit-graph-chain >actual &&
420 test_cmp expect actual