]>
Commit | Line | Data |
---|---|---|
102d7154 JC |
1 | #!/bin/sh |
2 | ||
3 | test_description='Test reffiles backend' | |
4 | ||
5 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main | |
6 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | |
ca13c3e9 PS |
7 | GIT_TEST_DEFAULT_REF_FORMAT=files |
8 | export GIT_TEST_DEFAULT_REF_FORMAT | |
102d7154 JC |
9 | |
10 | TEST_PASSES_SANITIZE_LEAK=true | |
11 | . ./test-lib.sh | |
12 | ||
102d7154 JC |
13 | test_expect_success 'setup' ' |
14 | git commit --allow-empty -m Initial && | |
15 | C=$(git rev-parse HEAD) && | |
16 | git commit --allow-empty -m Second && | |
17 | D=$(git rev-parse HEAD) && | |
18 | git commit --allow-empty -m Third && | |
19 | E=$(git rev-parse HEAD) | |
20 | ' | |
21 | ||
22 | test_expect_success 'empty directory should not fool rev-parse' ' | |
23 | prefix=refs/e-rev-parse && | |
24 | git update-ref $prefix/foo $C && | |
25 | git pack-refs --all && | |
26 | mkdir -p .git/$prefix/foo/bar/baz && | |
27 | echo "$C" >expected && | |
28 | git rev-parse $prefix/foo >actual && | |
29 | test_cmp expected actual | |
30 | ' | |
31 | ||
32 | test_expect_success 'empty directory should not fool for-each-ref' ' | |
33 | prefix=refs/e-for-each-ref && | |
34 | git update-ref $prefix/foo $C && | |
35 | git for-each-ref $prefix >expected && | |
36 | git pack-refs --all && | |
37 | mkdir -p .git/$prefix/foo/bar/baz && | |
38 | git for-each-ref $prefix >actual && | |
39 | test_cmp expected actual | |
40 | ' | |
41 | ||
42 | test_expect_success 'empty directory should not fool create' ' | |
43 | prefix=refs/e-create && | |
44 | mkdir -p .git/$prefix/foo/bar/baz && | |
45 | printf "create %s $C\n" $prefix/foo | | |
46 | git update-ref --stdin | |
47 | ' | |
48 | ||
49 | test_expect_success 'empty directory should not fool verify' ' | |
50 | prefix=refs/e-verify && | |
51 | git update-ref $prefix/foo $C && | |
52 | git pack-refs --all && | |
53 | mkdir -p .git/$prefix/foo/bar/baz && | |
54 | printf "verify %s $C\n" $prefix/foo | | |
55 | git update-ref --stdin | |
56 | ' | |
57 | ||
58 | test_expect_success 'empty directory should not fool 1-arg update' ' | |
59 | prefix=refs/e-update-1 && | |
60 | git update-ref $prefix/foo $C && | |
61 | git pack-refs --all && | |
62 | mkdir -p .git/$prefix/foo/bar/baz && | |
63 | printf "update %s $D\n" $prefix/foo | | |
64 | git update-ref --stdin | |
65 | ' | |
66 | ||
67 | test_expect_success 'empty directory should not fool 2-arg update' ' | |
68 | prefix=refs/e-update-2 && | |
69 | git update-ref $prefix/foo $C && | |
70 | git pack-refs --all && | |
71 | mkdir -p .git/$prefix/foo/bar/baz && | |
72 | printf "update %s $D $C\n" $prefix/foo | | |
73 | git update-ref --stdin | |
74 | ' | |
75 | ||
76 | test_expect_success 'empty directory should not fool 0-arg delete' ' | |
77 | prefix=refs/e-delete-0 && | |
78 | git update-ref $prefix/foo $C && | |
79 | git pack-refs --all && | |
80 | mkdir -p .git/$prefix/foo/bar/baz && | |
81 | printf "delete %s\n" $prefix/foo | | |
82 | git update-ref --stdin | |
83 | ' | |
84 | ||
85 | test_expect_success 'empty directory should not fool 1-arg delete' ' | |
86 | prefix=refs/e-delete-1 && | |
87 | git update-ref $prefix/foo $C && | |
88 | git pack-refs --all && | |
89 | mkdir -p .git/$prefix/foo/bar/baz && | |
90 | printf "delete %s $C\n" $prefix/foo | | |
91 | git update-ref --stdin | |
92 | ' | |
93 | ||
94 | test_expect_success 'non-empty directory blocks create' ' | |
95 | prefix=refs/ne-create && | |
96 | mkdir -p .git/$prefix/foo/bar && | |
97 | : >.git/$prefix/foo/bar/baz.lock && | |
98 | test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" && | |
99 | cat >expected <<-EOF && | |
100 | fatal: cannot lock ref $SQ$prefix/foo$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ | |
101 | EOF | |
102 | printf "%s\n" "update $prefix/foo $C" | | |
103 | test_must_fail git update-ref --stdin 2>output.err && | |
104 | test_cmp expected output.err && | |
105 | cat >expected <<-EOF && | |
106 | fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ | |
107 | EOF | |
108 | printf "%s\n" "update $prefix/foo $D $C" | | |
109 | test_must_fail git update-ref --stdin 2>output.err && | |
110 | test_cmp expected output.err | |
111 | ' | |
112 | ||
113 | test_expect_success 'broken reference blocks create' ' | |
114 | prefix=refs/broken-create && | |
115 | mkdir -p .git/$prefix && | |
116 | echo "gobbledigook" >.git/$prefix/foo && | |
117 | test_when_finished "rm -f .git/$prefix/foo" && | |
118 | cat >expected <<-EOF && | |
119 | fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken | |
120 | EOF | |
121 | printf "%s\n" "update $prefix/foo $C" | | |
122 | test_must_fail git update-ref --stdin 2>output.err && | |
123 | test_cmp expected output.err && | |
124 | cat >expected <<-EOF && | |
125 | fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken | |
126 | EOF | |
127 | printf "%s\n" "update $prefix/foo $D $C" | | |
128 | test_must_fail git update-ref --stdin 2>output.err && | |
129 | test_cmp expected output.err | |
130 | ' | |
131 | ||
132 | test_expect_success 'non-empty directory blocks indirect create' ' | |
133 | prefix=refs/ne-indirect-create && | |
134 | git symbolic-ref $prefix/symref $prefix/foo && | |
135 | mkdir -p .git/$prefix/foo/bar && | |
136 | : >.git/$prefix/foo/bar/baz.lock && | |
137 | test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" && | |
138 | cat >expected <<-EOF && | |
139 | fatal: cannot lock ref $SQ$prefix/symref$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ | |
140 | EOF | |
141 | printf "%s\n" "update $prefix/symref $C" | | |
142 | test_must_fail git update-ref --stdin 2>output.err && | |
143 | test_cmp expected output.err && | |
144 | cat >expected <<-EOF && | |
145 | fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ | |
146 | EOF | |
147 | printf "%s\n" "update $prefix/symref $D $C" | | |
148 | test_must_fail git update-ref --stdin 2>output.err && | |
149 | test_cmp expected output.err | |
150 | ' | |
151 | ||
152 | test_expect_success 'broken reference blocks indirect create' ' | |
153 | prefix=refs/broken-indirect-create && | |
154 | git symbolic-ref $prefix/symref $prefix/foo && | |
155 | echo "gobbledigook" >.git/$prefix/foo && | |
156 | test_when_finished "rm -f .git/$prefix/foo" && | |
157 | cat >expected <<-EOF && | |
158 | fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken | |
159 | EOF | |
160 | printf "%s\n" "update $prefix/symref $C" | | |
161 | test_must_fail git update-ref --stdin 2>output.err && | |
162 | test_cmp expected output.err && | |
163 | cat >expected <<-EOF && | |
164 | fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken | |
165 | EOF | |
166 | printf "%s\n" "update $prefix/symref $D $C" | | |
167 | test_must_fail git update-ref --stdin 2>output.err && | |
168 | test_cmp expected output.err | |
169 | ' | |
170 | ||
171 | test_expect_success 'no bogus intermediate values during delete' ' | |
172 | prefix=refs/slow-transaction && | |
173 | # Set up a reference with differing loose and packed versions: | |
174 | git update-ref $prefix/foo $C && | |
175 | git pack-refs --all && | |
176 | git update-ref $prefix/foo $D && | |
177 | # Now try to update the reference, but hold the `packed-refs` lock | |
178 | # for a while to see what happens while the process is blocked: | |
179 | : >.git/packed-refs.lock && | |
180 | test_when_finished "rm -f .git/packed-refs.lock" && | |
181 | { | |
182 | # Note: the following command is intentionally run in the | |
183 | # background. We increase the timeout so that `update-ref` | |
184 | # attempts to acquire the `packed-refs` lock for much longer | |
185 | # than it takes for us to do the check then delete it: | |
186 | git -c core.packedrefstimeout=30000 update-ref -d $prefix/foo & | |
187 | } && | |
188 | pid2=$! && | |
189 | # Give update-ref plenty of time to get to the point where it tries | |
190 | # to lock packed-refs: | |
191 | sleep 1 && | |
192 | # Make sure that update-ref did not complete despite the lock: | |
193 | kill -0 $pid2 && | |
194 | # Verify that the reference still has its old value: | |
195 | sha1=$(git rev-parse --verify --quiet $prefix/foo || echo undefined) && | |
196 | case "$sha1" in | |
197 | $D) | |
198 | # This is what we hope for; it means that nothing | |
199 | # user-visible has changed yet. | |
200 | : ;; | |
201 | undefined) | |
202 | # This is not correct; it means the deletion has happened | |
203 | # already even though update-ref should not have been | |
204 | # able to acquire the lock yet. | |
205 | echo "$prefix/foo deleted prematurely" && | |
206 | break | |
207 | ;; | |
208 | $C) | |
209 | # This value should never be seen. Probably the loose | |
210 | # reference has been deleted but the packed reference | |
211 | # is still there: | |
212 | echo "$prefix/foo incorrectly observed to be C" && | |
213 | break | |
214 | ;; | |
215 | *) | |
216 | # WTF? | |
217 | echo "unexpected value observed for $prefix/foo: $sha1" && | |
218 | break | |
219 | ;; | |
220 | esac >out && | |
221 | rm -f .git/packed-refs.lock && | |
222 | wait $pid2 && | |
223 | test_must_be_empty out && | |
224 | test_must_fail git rev-parse --verify --quiet $prefix/foo | |
225 | ' | |
226 | ||
227 | test_expect_success 'delete fails cleanly if packed-refs file is locked' ' | |
228 | prefix=refs/locked-packed-refs && | |
229 | # Set up a reference with differing loose and packed versions: | |
230 | git update-ref $prefix/foo $C && | |
231 | git pack-refs --all && | |
232 | git update-ref $prefix/foo $D && | |
233 | git for-each-ref $prefix >unchanged && | |
234 | # Now try to delete it while the `packed-refs` lock is held: | |
235 | : >.git/packed-refs.lock && | |
236 | test_when_finished "rm -f .git/packed-refs.lock" && | |
237 | test_must_fail git update-ref -d $prefix/foo >out 2>err && | |
238 | git for-each-ref $prefix >actual && | |
239 | test_grep "Unable to create $SQ.*packed-refs.lock$SQ: " err && | |
240 | test_cmp unchanged actual | |
241 | ' | |
242 | ||
243 | test_expect_success 'delete fails cleanly if packed-refs.new write fails' ' | |
244 | # Setup and expectations are similar to the test above. | |
245 | prefix=refs/failed-packed-refs && | |
246 | git update-ref $prefix/foo $C && | |
247 | git pack-refs --all && | |
248 | git update-ref $prefix/foo $D && | |
249 | git for-each-ref $prefix >unchanged && | |
250 | # This should not happen in practice, but it is an easy way to get a | |
251 | # reliable error (we open with create_tempfile(), which uses O_EXCL). | |
252 | : >.git/packed-refs.new && | |
253 | test_when_finished "rm -f .git/packed-refs.new" && | |
254 | test_must_fail git update-ref -d $prefix/foo && | |
255 | git for-each-ref $prefix >actual && | |
256 | test_cmp unchanged actual | |
257 | ' | |
258 | ||
e74d9f57 JC |
259 | RWT="test-tool ref-store worktree:wt" |
260 | RMAIN="test-tool ref-store worktree:main" | |
261 | ||
262 | test_expect_success 'setup worktree' ' | |
263 | test_commit first && | |
264 | git worktree add -b wt-main wt && | |
265 | ( | |
266 | cd wt && | |
267 | test_commit second | |
268 | ) | |
269 | ' | |
270 | ||
271 | # Some refs (refs/bisect/*, pseudorefs) are kept per worktree, so they should | |
272 | # only appear in the for-each-reflog output if it is called from the correct | |
273 | # worktree, which is exercised in this test. This test is poorly written for | |
274 | # mulitple reasons: 1) it creates invalidly formatted log entres. 2) it uses | |
275 | # direct FS access for creating the reflogs. 3) PSEUDO-WT and refs/bisect/random | |
276 | # do not create reflogs by default, so it is not testing a realistic scenario. | |
277 | test_expect_success 'for_each_reflog()' ' | |
d037212d | 278 | echo $ZERO_OID >.git/logs/PSEUDO_MAIN_HEAD && |
e74d9f57 | 279 | mkdir -p .git/logs/refs/bisect && |
d037212d | 280 | echo $ZERO_OID >.git/logs/refs/bisect/random && |
e74d9f57 | 281 | |
d037212d | 282 | echo $ZERO_OID >.git/worktrees/wt/logs/PSEUDO_WT_HEAD && |
e74d9f57 | 283 | mkdir -p .git/worktrees/wt/logs/refs/bisect && |
d037212d | 284 | echo $ZERO_OID >.git/worktrees/wt/logs/refs/bisect/wt-random && |
e74d9f57 | 285 | |
31f89839 | 286 | $RWT for-each-reflog >actual && |
e74d9f57 | 287 | cat >expected <<-\EOF && |
31f89839 | 288 | HEAD |
d037212d | 289 | PSEUDO_WT_HEAD |
31f89839 PS |
290 | refs/bisect/wt-random |
291 | refs/heads/main | |
292 | refs/heads/wt-main | |
e74d9f57 JC |
293 | EOF |
294 | test_cmp expected actual && | |
295 | ||
31f89839 | 296 | $RMAIN for-each-reflog >actual && |
e74d9f57 | 297 | cat >expected <<-\EOF && |
31f89839 | 298 | HEAD |
d037212d | 299 | PSEUDO_MAIN_HEAD |
31f89839 PS |
300 | refs/bisect/random |
301 | refs/heads/main | |
302 | refs/heads/wt-main | |
e74d9f57 JC |
303 | EOF |
304 | test_cmp expected actual | |
305 | ' | |
306 | ||
c02ce758 JC |
307 | # Triggering the bug detected by this test requires a newline to fall |
308 | # exactly BUFSIZ-1 bytes from the end of the file. We don't know | |
309 | # what that value is, since it's platform dependent. However, if | |
310 | # we choose some value N, we also catch any D which divides N evenly | |
311 | # (since we will read backwards in chunks of D). So we choose 8K, | |
312 | # which catches glibc (with an 8K BUFSIZ) and *BSD (1K). | |
313 | # | |
314 | # Each line is 114 characters, so we need 75 to still have a few before the | |
315 | # last 8K. The 89-character padding on the final entry lines up our | |
316 | # newline exactly. | |
317 | test_expect_success SHA1 'parsing reverse reflogs at BUFSIZ boundaries' ' | |
318 | git checkout -b reflogskip && | |
319 | zf=$(test_oid zero_2) && | |
320 | ident="abc <xyz> 0000000001 +0000" && | |
321 | for i in $(test_seq 1 75); do | |
322 | printf "$zf%02d $zf%02d %s\t" $i $(($i+1)) "$ident" && | |
323 | if test $i = 75; then | |
324 | for j in $(test_seq 1 89); do | |
325 | printf X || return 1 | |
326 | done | |
327 | else | |
328 | printf X | |
329 | fi && | |
330 | printf "\n" || return 1 | |
331 | done >.git/logs/refs/heads/reflogskip && | |
332 | git rev-parse reflogskip@{73} >actual && | |
333 | echo ${zf}03 >expect && | |
334 | test_cmp expect actual | |
335 | ' | |
336 | ||
337 | # This test takes a lock on an individual ref; this is not supported in | |
338 | # reftable. | |
339 | test_expect_success 'reflog expire operates on symref not referrent' ' | |
340 | git branch --create-reflog the_symref && | |
341 | git branch --create-reflog referrent && | |
342 | git update-ref referrent HEAD && | |
343 | git symbolic-ref refs/heads/the_symref refs/heads/referrent && | |
344 | test_when_finished "rm -f .git/refs/heads/referrent.lock" && | |
345 | touch .git/refs/heads/referrent.lock && | |
346 | git reflog expire --expire=all the_symref | |
347 | ' | |
348 | ||
349 | test_expect_success 'empty reflog' ' | |
350 | test_when_finished "rm -rf empty" && | |
351 | git init empty && | |
352 | test_commit -C empty A && | |
353 | >empty/.git/logs/refs/heads/foo && | |
354 | git -C empty reflog expire --all 2>err && | |
355 | test_must_be_empty err | |
356 | ' | |
357 | ||
dfc9486c JC |
358 | test_expect_success SYMLINKS 'ref resolution not confused by broken symlinks' ' |
359 | ln -s does-not-exist .git/refs/heads/broken && | |
360 | test_must_fail git rev-parse --verify broken | |
361 | ' | |
362 | ||
1030d140 JC |
363 | test_expect_success 'log diagnoses bogus HEAD hash' ' |
364 | git init empty && | |
365 | test_when_finished "rm -rf empty" && | |
366 | echo 1234abcd >empty/.git/refs/heads/main && | |
367 | test_must_fail git -C empty log 2>stderr && | |
368 | test_grep broken stderr | |
369 | ' | |
370 | ||
371 | test_expect_success 'log diagnoses bogus HEAD symref' ' | |
372 | git init empty && | |
373 | test-tool -C empty ref-store main create-symref HEAD refs/heads/invalid.lock && | |
374 | test_must_fail git -C empty log 2>stderr && | |
375 | test_grep broken stderr && | |
376 | test_must_fail git -C empty log --default totally-bogus 2>stderr && | |
377 | test_grep broken stderr | |
378 | ' | |
379 | ||
161d9816 PS |
380 | test_expect_success 'empty directory removal' ' |
381 | git branch d1/d2/r1 HEAD && | |
382 | git branch d1/r2 HEAD && | |
383 | test_path_is_file .git/refs/heads/d1/d2/r1 && | |
384 | test_path_is_file .git/logs/refs/heads/d1/d2/r1 && | |
385 | git branch -d d1/d2/r1 && | |
386 | test_must_fail git show-ref --verify -q refs/heads/d1/d2 && | |
387 | test_must_fail git show-ref --verify -q logs/refs/heads/d1/d2 && | |
388 | test_path_is_file .git/refs/heads/d1/r2 && | |
389 | test_path_is_file .git/logs/refs/heads/d1/r2 | |
390 | ' | |
391 | ||
392 | test_expect_success 'symref empty directory removal' ' | |
393 | git branch e1/e2/r1 HEAD && | |
394 | git branch e1/r2 HEAD && | |
395 | git checkout e1/e2/r1 && | |
396 | test_when_finished "git checkout main" && | |
397 | test_path_is_file .git/refs/heads/e1/e2/r1 && | |
398 | test_path_is_file .git/logs/refs/heads/e1/e2/r1 && | |
399 | git update-ref -d HEAD && | |
400 | test_must_fail git show-ref --verify -q refs/heads/e1/e2 && | |
401 | test_must_fail git show-ref --verify -q logs/refs/heads/e1/e2 && | |
402 | test_path_is_file .git/refs/heads/e1/r2 && | |
403 | test_path_is_file .git/logs/refs/heads/e1/r2 && | |
404 | test_path_is_file .git/logs/HEAD | |
405 | ' | |
406 | ||
407 | test_expect_success 'directory not created deleting packed ref' ' | |
408 | git branch d1/d2/r1 HEAD && | |
409 | git pack-refs --all && | |
410 | test_path_is_missing .git/refs/heads/d1/d2 && | |
411 | git update-ref -d refs/heads/d1/d2/r1 && | |
412 | test_path_is_missing .git/refs/heads/d1/d2 && | |
413 | test_path_is_missing .git/refs/heads/d1 | |
414 | ' | |
415 | ||
416 | test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for u is a symlink' ' | |
417 | git branch --create-reflog u && | |
418 | mv .git/logs/refs/heads/u real-u && | |
419 | ln -s real-u .git/logs/refs/heads/u && | |
420 | test_must_fail git branch -m u v | |
421 | ' | |
422 | ||
423 | test_expect_success SYMLINKS 'git branch -m with symlinked .git/refs' ' | |
424 | test_when_finished "rm -rf subdir" && | |
425 | git init --bare subdir && | |
426 | ||
ce09c692 | 427 | rm -rf subdir/refs subdir/objects subdir/packed-refs && |
161d9816 PS |
428 | ln -s ../.git/refs subdir/refs && |
429 | ln -s ../.git/objects subdir/objects && | |
430 | ln -s ../.git/packed-refs subdir/packed-refs && | |
431 | ||
432 | git -C subdir rev-parse --absolute-git-dir >subdir.dir && | |
433 | git rev-parse --absolute-git-dir >our.dir && | |
434 | ! test_cmp subdir.dir our.dir && | |
435 | ||
436 | git -C subdir log && | |
437 | git -C subdir branch rename-src && | |
438 | git rev-parse rename-src >expect && | |
439 | git -C subdir branch -m rename-src rename-dest && | |
440 | git rev-parse rename-dest >actual && | |
441 | test_cmp expect actual && | |
442 | git branch -D rename-dest | |
443 | ' | |
444 | ||
445 | test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' ' | |
446 | git checkout main && | |
447 | mv .git/logs actual_logs && | |
448 | cmd //c "mklink /D .git\logs ..\actual_logs" && | |
449 | git rebase -f HEAD^ && | |
450 | test -L .git/logs && | |
451 | rm .git/logs && | |
452 | mv actual_logs .git/logs | |
453 | ' | |
454 | ||
455 | test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' ' | |
456 | umask 077 && | |
457 | git config core.sharedRepository group && | |
458 | git reflog expire --all && | |
459 | actual="$(ls -l .git/logs/refs/heads/main)" && | |
460 | case "$actual" in | |
461 | -rw-rw-*) | |
462 | : happy | |
463 | ;; | |
464 | *) | |
465 | echo Ooops, .git/logs/refs/heads/main is not 066x [$actual] | |
466 | false | |
467 | ;; | |
468 | esac | |
469 | ' | |
470 | ||
102d7154 | 471 | test_done |