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