1#!/bin/sh
2
3test_description='split index mode tests'
4
5. ./test-lib.sh
6
7# We need total control of index splitting here
8sane_unset GIT_TEST_SPLIT_INDEX
9
10# Testing a hard coded SHA against an index with an extension
11# that can vary from run to run is problematic so we disable
12# those extensions.
13sane_unset GIT_TEST_FSMONITOR
14sane_unset GIT_TEST_INDEX_THREADS
15
16test_expect_success 'enable split index' '
17 git config splitIndex.maxPercentChange 100 &&
18 git update-index --split-index &&
19 test-tool dump-split-index .git/index >actual &&
20 indexversion=$(test-tool index-version <.git/index) &&
21 if test "$indexversion" = "4"
22 then
23 own=3527df833c6c100d3d1d921a9a782d62a8be4b58
24 base=746f7ab2ed44fb839efdfbffcf399d0b113fb4cb
25 else
26 own=5e9b60117ece18da410ddecc8b8d43766a0e4204
27 base=4370042739b31cd17a5c5cd6043a77c9a00df113
28 fi &&
29 cat >expect <<-EOF &&
30 own $own
31 base $base
32 replacements:
33 deletions:
34 EOF
35 test_cmp expect actual
36'
37
38test_expect_success 'add one file' '
39 : >one &&
40 git update-index --add one &&
41 git ls-files --stage >ls-files.actual &&
42 cat >ls-files.expect <<-EOF &&
43 100644 $EMPTY_BLOB 0 one
44 EOF
45 test_cmp ls-files.expect ls-files.actual &&
46
47 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
48 cat >expect <<-EOF &&
49 base $base
50 100644 $EMPTY_BLOB 0 one
51 replacements:
52 deletions:
53 EOF
54 test_cmp expect actual
55'
56
57test_expect_success 'disable split index' '
58 git update-index --no-split-index &&
59 git ls-files --stage >ls-files.actual &&
60 cat >ls-files.expect <<-EOF &&
61 100644 $EMPTY_BLOB 0 one
62 EOF
63 test_cmp ls-files.expect ls-files.actual &&
64
65 BASE=$(test-tool dump-split-index .git/index | sed -n "s/^own/base/p") &&
66 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
67 cat >expect <<-EOF &&
68 not a split index
69 EOF
70 test_cmp expect actual
71'
72
73test_expect_success 'enable split index again, "one" now belongs to base index"' '
74 git update-index --split-index &&
75 git ls-files --stage >ls-files.actual &&
76 cat >ls-files.expect <<-EOF &&
77 100644 $EMPTY_BLOB 0 one
78 EOF
79 test_cmp ls-files.expect ls-files.actual &&
80
81 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
82 cat >expect <<-EOF &&
83 $BASE
84 replacements:
85 deletions:
86 EOF
87 test_cmp expect actual
88'
89
90test_expect_success 'modify original file, base index untouched' '
91 echo modified >one &&
92 git update-index one &&
93 git ls-files --stage >ls-files.actual &&
94 cat >ls-files.expect <<-EOF &&
95 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
96 EOF
97 test_cmp ls-files.expect ls-files.actual &&
98
99 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
100 q_to_tab >expect <<-EOF &&
101 $BASE
102 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
103 replacements: 0
104 deletions:
105 EOF
106 test_cmp expect actual
107'
108
109test_expect_success 'add another file, which stays index' '
110 : >two &&
111 git update-index --add two &&
112 git ls-files --stage >ls-files.actual &&
113 cat >ls-files.expect <<-EOF &&
114 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
115 100644 $EMPTY_BLOB 0 two
116 EOF
117 test_cmp ls-files.expect ls-files.actual &&
118
119 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
120 q_to_tab >expect <<-EOF &&
121 $BASE
122 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
123 100644 $EMPTY_BLOB 0 two
124 replacements: 0
125 deletions:
126 EOF
127 test_cmp expect actual
128'
129
130test_expect_success 'remove file not in base index' '
131 git update-index --force-remove two &&
132 git ls-files --stage >ls-files.actual &&
133 cat >ls-files.expect <<-EOF &&
134 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
135 EOF
136 test_cmp ls-files.expect ls-files.actual &&
137
138 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
139 q_to_tab >expect <<-EOF &&
140 $BASE
141 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
142 replacements: 0
143 deletions:
144 EOF
145 test_cmp expect actual
146'
147
148test_expect_success 'remove file in base index' '
149 git update-index --force-remove one &&
150 git ls-files --stage >ls-files.actual &&
151 test_must_be_empty ls-files.actual &&
152
153 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
154 cat >expect <<-EOF &&
155 $BASE
156 replacements:
157 deletions: 0
158 EOF
159 test_cmp expect actual
160'
161
162test_expect_success 'add original file back' '
163 : >one &&
164 git update-index --add one &&
165 git ls-files --stage >ls-files.actual &&
166 cat >ls-files.expect <<-EOF &&
167 100644 $EMPTY_BLOB 0 one
168 EOF
169 test_cmp ls-files.expect ls-files.actual &&
170
171 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
172 cat >expect <<-EOF &&
173 $BASE
174 100644 $EMPTY_BLOB 0 one
175 replacements:
176 deletions: 0
177 EOF
178 test_cmp expect actual
179'
180
181test_expect_success 'add new file' '
182 : >two &&
183 git update-index --add two &&
184 git ls-files --stage >actual &&
185 cat >expect <<-EOF &&
186 100644 $EMPTY_BLOB 0 one
187 100644 $EMPTY_BLOB 0 two
188 EOF
189 test_cmp expect actual
190'
191
192test_expect_success 'unify index, two files remain' '
193 git update-index --no-split-index &&
194 git ls-files --stage >ls-files.actual &&
195 cat >ls-files.expect <<-EOF &&
196 100644 $EMPTY_BLOB 0 one
197 100644 $EMPTY_BLOB 0 two
198 EOF
199 test_cmp ls-files.expect ls-files.actual &&
200
201 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
202 cat >expect <<-EOF &&
203 not a split index
204 EOF
205 test_cmp expect actual
206'
207
208test_expect_success 'rev-parse --shared-index-path' '
209 test_create_repo split-index &&
210 (
211 cd split-index &&
212 git update-index --split-index &&
213 echo .git/sharedindex* >expect &&
214 git rev-parse --shared-index-path >actual &&
215 test_cmp expect actual &&
216 mkdir subdirectory &&
217 cd subdirectory &&
218 echo ../.git/sharedindex* >expect &&
219 git rev-parse --shared-index-path >actual &&
220 test_cmp expect actual
221 )
222'
223
224test_expect_success 'set core.splitIndex config variable to true' '
225 git config core.splitIndex true &&
226 : >three &&
227 git update-index --add three &&
228 git ls-files --stage >ls-files.actual &&
229 cat >ls-files.expect <<-EOF &&
230 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
231 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 three
232 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
233 EOF
234 test_cmp ls-files.expect ls-files.actual &&
235 BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
236 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
237 cat >expect <<-EOF &&
238 $BASE
239 replacements:
240 deletions:
241 EOF
242 test_cmp expect actual
243'
244
245test_expect_success 'set core.splitIndex config variable to false' '
246 git config core.splitIndex false &&
247 git update-index --force-remove three &&
248 git ls-files --stage >ls-files.actual &&
249 cat >ls-files.expect <<-EOF &&
250 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
251 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
252 EOF
253 test_cmp ls-files.expect ls-files.actual &&
254 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
255 cat >expect <<-EOF &&
256 not a split index
257 EOF
258 test_cmp expect actual
259'
260
261test_expect_success 'set core.splitIndex config variable to true' '
262 git config core.splitIndex true &&
263 : >three &&
264 git update-index --add three &&
265 BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
266 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
267 cat >expect <<-EOF &&
268 $BASE
269 replacements:
270 deletions:
271 EOF
272 test_cmp expect actual &&
273 : >four &&
274 git update-index --add four &&
275 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
276 cat >expect <<-EOF &&
277 $BASE
278 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 four
279 replacements:
280 deletions:
281 EOF
282 test_cmp expect actual
283'
284
285test_expect_success 'check behavior with splitIndex.maxPercentChange unset' '
286 git config --unset splitIndex.maxPercentChange &&
287 : >five &&
288 git update-index --add five &&
289 BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
290 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
291 cat >expect <<-EOF &&
292 $BASE
293 replacements:
294 deletions:
295 EOF
296 test_cmp expect actual &&
297 : >six &&
298 git update-index --add six &&
299 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
300 cat >expect <<-EOF &&
301 $BASE
302 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 six
303 replacements:
304 deletions:
305 EOF
306 test_cmp expect actual
307'
308
309test_expect_success 'check splitIndex.maxPercentChange set to 0' '
310 git config splitIndex.maxPercentChange 0 &&
311 : >seven &&
312 git update-index --add seven &&
313 BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
314 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
315 cat >expect <<-EOF &&
316 $BASE
317 replacements:
318 deletions:
319 EOF
320 test_cmp expect actual &&
321 : >eight &&
322 git update-index --add eight &&
323 BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
324 test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
325 cat >expect <<-EOF &&
326 $BASE
327 replacements:
328 deletions:
329 EOF
330 test_cmp expect actual
331'
332
333test_expect_success 'shared index files expire after 2 weeks by default' '
334 : >ten &&
335 git update-index --add ten &&
336 test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
337 just_under_2_weeks_ago=$((5-14*86400)) &&
338 test-tool chmtime =$just_under_2_weeks_ago .git/sharedindex.* &&
339 : >eleven &&
340 git update-index --add eleven &&
341 test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
342 just_over_2_weeks_ago=$((-1-14*86400)) &&
343 test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
344 : >twelve &&
345 git update-index --add twelve &&
346 test $(ls .git/sharedindex.* | wc -l) -le 2
347'
348
349test_expect_success 'check splitIndex.sharedIndexExpire set to 16 days' '
350 git config splitIndex.sharedIndexExpire "16.days.ago" &&
351 test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
352 : >thirteen &&
353 git update-index --add thirteen &&
354 test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
355 just_over_16_days_ago=$((-1-16*86400)) &&
356 test-tool chmtime =$just_over_16_days_ago .git/sharedindex.* &&
357 : >fourteen &&
358 git update-index --add fourteen &&
359 test $(ls .git/sharedindex.* | wc -l) -le 2
360'
361
362test_expect_success 'check splitIndex.sharedIndexExpire set to "never" and "now"' '
363 git config splitIndex.sharedIndexExpire never &&
364 just_10_years_ago=$((-365*10*86400)) &&
365 test-tool chmtime =$just_10_years_ago .git/sharedindex.* &&
366 : >fifteen &&
367 git update-index --add fifteen &&
368 test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
369 git config splitIndex.sharedIndexExpire now &&
370 just_1_second_ago=-1 &&
371 test-tool chmtime =$just_1_second_ago .git/sharedindex.* &&
372 : >sixteen &&
373 git update-index --add sixteen &&
374 test $(ls .git/sharedindex.* | wc -l) -le 2
375'
376
377while read -r mode modebits
378do
379 test_expect_success POSIXPERM "split index respects core.sharedrepository $mode" '
380 # Remove existing shared index files
381 git config core.splitIndex false &&
382 git update-index --force-remove one &&
383 rm -f .git/sharedindex.* &&
384 # Create one new shared index file
385 git config core.sharedrepository "$mode" &&
386 git config core.splitIndex true &&
387 : >one &&
388 git update-index --add one &&
389 echo "$modebits" >expect &&
390 test_modebits .git/index >actual &&
391 test_cmp expect actual &&
392 shared=$(ls .git/sharedindex.*) &&
393 case "$shared" in
394 *" "*)
395 # we have more than one???
396 false ;;
397 *)
398 test_modebits "$shared" >actual &&
399 test_cmp expect actual ;;
400 esac
401 '
402done <<\EOF
4030666 -rw-rw-rw-
4040642 -rw-r---w-
405EOF
406
407test_expect_success POSIXPERM,SANITY 'graceful handling when splitting index is not allowed' '
408 test_create_repo ro &&
409 (
410 cd ro &&
411 test_commit initial &&
412 git update-index --split-index &&
413 test -f .git/sharedindex.*
414 ) &&
415 cp ro/.git/index new-index &&
416 test_when_finished "chmod u+w ro/.git" &&
417 chmod u-w ro/.git &&
418 GIT_INDEX_FILE="$(pwd)/new-index" git -C ro update-index --split-index &&
419 chmod u+w ro/.git &&
420 rm ro/.git/sharedindex.* &&
421 GIT_INDEX_FILE=new-index git ls-files >actual &&
422 echo initial.t >expected &&
423 test_cmp expected actual
424'
425
426test_expect_success 'writing split index with null sha1 does not write cache tree' '
427 git config core.splitIndex true &&
428 git config splitIndex.maxPercentChange 0 &&
429 git commit -m "commit" &&
430 {
431 git ls-tree HEAD &&
432 printf "160000 commit $ZERO_OID\\tbroken\\n"
433 } >broken-tree &&
434 echo "add broken entry" >msg &&
435
436 tree=$(git mktree <broken-tree) &&
437 test_tick &&
438 commit=$(git commit-tree $tree -p HEAD <msg) &&
439 git update-ref HEAD "$commit" &&
440 GIT_ALLOW_NULL_SHA1=1 git reset --hard &&
441 test_might_fail test-tool dump-cache-tree >cache-tree.out &&
442 test_line_count = 0 cache-tree.out
443'
444
445test_done