Merge branch 'js/mingw-open-in-gdb' into maint
[git] / t / t5324-split-commit-graph.sh
1 #!/bin/sh
2
3 test_description='split commit graph'
4 . ./test-lib.sh
5
6 GIT_TEST_COMMIT_GRAPH=0
7
8 test_expect_success 'setup repo' '
9         git init &&
10         git config core.commitGraph true &&
11         git config gc.writeCommitGraph false &&
12         infodir=".git/objects/info" &&
13         graphdir="$infodir/commit-graphs" &&
14         test_oid_init
15 '
16
17 graph_read_expect() {
18         NUM_BASE=0
19         if test ! -z $2
20         then
21                 NUM_BASE=$2
22         fi
23         cat >expect <<- EOF
24         header: 43475048 1 1 3 $NUM_BASE
25         num_commits: $1
26         chunks: oid_fanout oid_lookup commit_metadata
27         EOF
28         test-tool read-graph >output &&
29         test_cmp expect output
30 }
31
32 test_expect_success 'create commits and write commit-graph' '
33         for i in $(test_seq 3)
34         do
35                 test_commit $i &&
36                 git branch commits/$i || return 1
37         done &&
38         git commit-graph write --reachable &&
39         test_path_is_file $infodir/commit-graph &&
40         graph_read_expect 3
41 '
42
43 graph_git_two_modes() {
44         git -c core.commitGraph=true $1 >output
45         git -c core.commitGraph=false $1 >expect
46         test_cmp expect output
47 }
48
49 graph_git_behavior() {
50         MSG=$1
51         BRANCH=$2
52         COMPARE=$3
53         test_expect_success "check normal git operations: $MSG" '
54                 graph_git_two_modes "log --oneline $BRANCH" &&
55                 graph_git_two_modes "log --topo-order $BRANCH" &&
56                 graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
57                 graph_git_two_modes "branch -vv" &&
58                 graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
59         '
60 }
61
62 graph_git_behavior 'graph exists' commits/3 commits/1
63
64 verify_chain_files_exist() {
65         for hash in $(cat $1/commit-graph-chain)
66         do
67                 test_path_is_file $1/graph-$hash.graph || return 1
68         done
69 }
70
71 test_expect_success 'add more commits, and write a new base graph' '
72         git reset --hard commits/1 &&
73         for i in $(test_seq 4 5)
74         do
75                 test_commit $i &&
76                 git branch commits/$i || return 1
77         done &&
78         git reset --hard commits/2 &&
79         for i in $(test_seq 6 10)
80         do
81                 test_commit $i &&
82                 git branch commits/$i || return 1
83         done &&
84         git reset --hard commits/2 &&
85         git merge commits/4 &&
86         git branch merge/1 &&
87         git reset --hard commits/4 &&
88         git merge commits/6 &&
89         git branch merge/2 &&
90         git commit-graph write --reachable &&
91         graph_read_expect 12
92 '
93
94 test_expect_success 'fork and fail to base a chain on a commit-graph file' '
95         test_when_finished rm -rf fork &&
96         git clone . fork &&
97         (
98                 cd fork &&
99                 rm .git/objects/info/commit-graph &&
100                 echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
101                 test_commit new-commit &&
102                 git commit-graph write --reachable --split &&
103                 test_path_is_file $graphdir/commit-graph-chain &&
104                 test_line_count = 1 $graphdir/commit-graph-chain &&
105                 verify_chain_files_exist $graphdir
106         )
107 '
108
109 test_expect_success 'add three more commits, write a tip graph' '
110         git reset --hard commits/3 &&
111         git merge merge/1 &&
112         git merge commits/5 &&
113         git merge merge/2 &&
114         git branch merge/3 &&
115         git commit-graph write --reachable --split &&
116         test_path_is_missing $infodir/commit-graph &&
117         test_path_is_file $graphdir/commit-graph-chain &&
118         ls $graphdir/graph-*.graph >graph-files &&
119         test_line_count = 2 graph-files &&
120         verify_chain_files_exist $graphdir
121 '
122
123 graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2
124
125 test_expect_success 'add one commit, write a tip graph' '
126         test_commit 11 &&
127         git branch commits/11 &&
128         git commit-graph write --reachable --split &&
129         test_path_is_missing $infodir/commit-graph &&
130         test_path_is_file $graphdir/commit-graph-chain &&
131         ls $graphdir/graph-*.graph >graph-files &&
132         test_line_count = 3 graph-files &&
133         verify_chain_files_exist $graphdir
134 '
135
136 graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits/6
137
138 test_expect_success 'add one commit, write a merged graph' '
139         test_commit 12 &&
140         git branch commits/12 &&
141         git commit-graph write --reachable --split &&
142         test_path_is_file $graphdir/commit-graph-chain &&
143         test_line_count = 2 $graphdir/commit-graph-chain &&
144         ls $graphdir/graph-*.graph >graph-files &&
145         test_line_count = 2 graph-files &&
146         verify_chain_files_exist $graphdir
147 '
148
149 graph_git_behavior 'merged commit-graph: commit 12 vs 6' commits/12 commits/6
150
151 test_expect_success 'create fork and chain across alternate' '
152         git clone . fork &&
153         (
154                 cd fork &&
155                 git config core.commitGraph true &&
156                 rm -rf $graphdir &&
157                 echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
158                 test_commit 13 &&
159                 git branch commits/13 &&
160                 git commit-graph write --reachable --split &&
161                 test_path_is_file $graphdir/commit-graph-chain &&
162                 test_line_count = 3 $graphdir/commit-graph-chain &&
163                 ls $graphdir/graph-*.graph >graph-files &&
164                 test_line_count = 1 graph-files &&
165                 git -c core.commitGraph=true  rev-list HEAD >expect &&
166                 git -c core.commitGraph=false rev-list HEAD >actual &&
167                 test_cmp expect actual &&
168                 test_commit 14 &&
169                 git commit-graph write --reachable --split --object-dir=.git/objects/ &&
170                 test_line_count = 3 $graphdir/commit-graph-chain &&
171                 ls $graphdir/graph-*.graph >graph-files &&
172                 test_line_count = 1 graph-files
173         )
174 '
175
176 graph_git_behavior 'alternate: commit 13 vs 6' commits/13 commits/6
177
178 test_expect_success 'test merge stragety constants' '
179         git clone . merge-2 &&
180         (
181                 cd merge-2 &&
182                 git config core.commitGraph true &&
183                 test_line_count = 2 $graphdir/commit-graph-chain &&
184                 test_commit 14 &&
185                 git commit-graph write --reachable --split --size-multiple=2 &&
186                 test_line_count = 3 $graphdir/commit-graph-chain
187
188         ) &&
189         git clone . merge-10 &&
190         (
191                 cd merge-10 &&
192                 git config core.commitGraph true &&
193                 test_line_count = 2 $graphdir/commit-graph-chain &&
194                 test_commit 14 &&
195                 git commit-graph write --reachable --split --size-multiple=10 &&
196                 test_line_count = 1 $graphdir/commit-graph-chain &&
197                 ls $graphdir/graph-*.graph >graph-files &&
198                 test_line_count = 1 graph-files
199         ) &&
200         git clone . merge-10-expire &&
201         (
202                 cd merge-10-expire &&
203                 git config core.commitGraph true &&
204                 test_line_count = 2 $graphdir/commit-graph-chain &&
205                 test_commit 15 &&
206                 git commit-graph write --reachable --split --size-multiple=10 --expire-time=1980-01-01 &&
207                 test_line_count = 1 $graphdir/commit-graph-chain &&
208                 ls $graphdir/graph-*.graph >graph-files &&
209                 test_line_count = 3 graph-files
210         ) &&
211         git clone --no-hardlinks . max-commits &&
212         (
213                 cd max-commits &&
214                 git config core.commitGraph true &&
215                 test_line_count = 2 $graphdir/commit-graph-chain &&
216                 test_commit 16 &&
217                 test_commit 17 &&
218                 git commit-graph write --reachable --split --max-commits=1 &&
219                 test_line_count = 1 $graphdir/commit-graph-chain &&
220                 ls $graphdir/graph-*.graph >graph-files &&
221                 test_line_count = 1 graph-files
222         )
223 '
224
225 test_expect_success 'remove commit-graph-chain file after flattening' '
226         git clone . flatten &&
227         (
228                 cd flatten &&
229                 test_line_count = 2 $graphdir/commit-graph-chain &&
230                 git commit-graph write --reachable &&
231                 test_path_is_missing $graphdir/commit-graph-chain &&
232                 ls $graphdir >graph-files &&
233                 test_line_count = 0 graph-files
234         )
235 '
236
237 corrupt_file() {
238         file=$1
239         pos=$2
240         data="${3:-\0}"
241         chmod a+w "$file" &&
242         printf "$data" | dd of="$file" bs=1 seek="$pos" conv=notrunc
243 }
244
245 test_expect_success 'verify hashes along chain, even in shallow' '
246         git clone --no-hardlinks . verify &&
247         (
248                 cd verify &&
249                 git commit-graph verify &&
250                 base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
251                 corrupt_file "$base_file" 1760 "\01" &&
252                 test_must_fail git commit-graph verify --shallow 2>test_err &&
253                 grep -v "^+" test_err >err &&
254                 test_i18ngrep "incorrect checksum" err
255         )
256 '
257
258 test_expect_success 'verify --shallow does not check base contents' '
259         git clone --no-hardlinks . verify-shallow &&
260         (
261                 cd verify-shallow &&
262                 git commit-graph verify &&
263                 base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
264                 corrupt_file "$base_file" 1000 "\01" &&
265                 git commit-graph verify --shallow &&
266                 test_must_fail git commit-graph verify 2>test_err &&
267                 grep -v "^+" test_err >err &&
268                 test_i18ngrep "incorrect checksum" err
269         )
270 '
271
272 test_expect_success 'warn on base graph chunk incorrect' '
273         git clone --no-hardlinks . base-chunk &&
274         (
275                 cd base-chunk &&
276                 git commit-graph verify &&
277                 base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
278                 corrupt_file "$base_file" 1376 "\01" &&
279                 git commit-graph verify --shallow 2>test_err &&
280                 grep -v "^+" test_err >err &&
281                 test_i18ngrep "commit-graph chain does not match" err
282         )
283 '
284
285 test_expect_success 'verify after commit-graph-chain corruption' '
286         git clone --no-hardlinks . verify-chain &&
287         (
288                 cd verify-chain &&
289                 corrupt_file "$graphdir/commit-graph-chain" 60 "G" &&
290                 git commit-graph verify 2>test_err &&
291                 grep -v "^+" test_err >err &&
292                 test_i18ngrep "invalid commit-graph chain" err &&
293                 corrupt_file "$graphdir/commit-graph-chain" 60 "A" &&
294                 git commit-graph verify 2>test_err &&
295                 grep -v "^+" test_err >err &&
296                 test_i18ngrep "unable to find all commit-graph files" err
297         )
298 '
299
300 test_expect_success 'verify across alternates' '
301         git clone --no-hardlinks . verify-alt &&
302         (
303                 cd verify-alt &&
304                 rm -rf $graphdir &&
305                 altdir="$(pwd)/../.git/objects" &&
306                 echo "$altdir" >.git/objects/info/alternates &&
307                 git commit-graph verify --object-dir="$altdir/" &&
308                 test_commit extra &&
309                 git commit-graph write --reachable --split &&
310                 tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
311                 corrupt_file "$tip_file" 100 "\01" &&
312                 test_must_fail git commit-graph verify --shallow 2>test_err &&
313                 grep -v "^+" test_err >err &&
314                 test_i18ngrep "commit-graph has incorrect fanout value" err
315         )
316 '
317
318 test_expect_success 'add octopus merge' '
319         git reset --hard commits/10 &&
320         git merge commits/3 commits/4 &&
321         git branch merge/octopus &&
322         git commit-graph write --reachable --split &&
323         git commit-graph verify --progress 2>err &&
324         test_line_count = 3 err &&
325         test_i18ngrep ! warning err &&
326         test_line_count = 3 $graphdir/commit-graph-chain
327 '
328
329 graph_git_behavior 'graph exists' merge/octopus commits/12
330
331 test_expect_success 'split across alternate where alternate is not split' '
332         git commit-graph write --reachable &&
333         test_path_is_file .git/objects/info/commit-graph &&
334         cp .git/objects/info/commit-graph . &&
335         git clone --no-hardlinks . alt-split &&
336         (
337                 cd alt-split &&
338                 rm -f .git/objects/info/commit-graph &&
339                 echo "$(pwd)"/../.git/objects >.git/objects/info/alternates &&
340                 test_commit 18 &&
341                 git commit-graph write --reachable --split &&
342                 test_line_count = 1 $graphdir/commit-graph-chain
343         ) &&
344         test_cmp commit-graph .git/objects/info/commit-graph
345 '
346
347 test_done