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