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