]> git.ipfire.org Git - thirdparty/git.git/blob - t/t5329-pack-objects-cruft.sh
clone: allow "--bare" with "-o"
[thirdparty/git.git] / t / t5329-pack-objects-cruft.sh
1 #!/bin/sh
2
3 test_description='cruft pack related pack-objects tests'
4 . ./test-lib.sh
5
6 objdir=.git/objects
7 packdir=$objdir/pack
8
9 basic_cruft_pack_tests () {
10 expire="$1"
11
12 test_expect_success "unreachable loose objects are packed (expire $expire)" '
13 git init repo &&
14 test_when_finished "rm -fr repo" &&
15 (
16 cd repo &&
17
18 test_commit base &&
19 git repack -Ad &&
20 test_commit loose &&
21
22 test-tool chmtime +2000 "$objdir/$(test_oid_to_path \
23 $(git rev-parse loose:loose.t))" &&
24 test-tool chmtime +1000 "$objdir/$(test_oid_to_path \
25 $(git rev-parse loose^{tree}))" &&
26
27 (
28 git rev-list --objects --no-object-names base..loose |
29 while read oid
30 do
31 path="$objdir/$(test_oid_to_path "$oid")" &&
32 printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")"
33 done |
34 sort -k1
35 ) >expect &&
36
37 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
38 cruft="$(echo $keep | git pack-objects --cruft \
39 --cruft-expiration="$expire" $packdir/pack)" &&
40 test-tool pack-mtimes "pack-$cruft.mtimes" >actual &&
41
42 test_cmp expect actual
43 )
44 '
45
46 test_expect_success "unreachable packed objects are packed (expire $expire)" '
47 git init repo &&
48 test_when_finished "rm -fr repo" &&
49 (
50 cd repo &&
51
52 test_commit packed &&
53 git repack -Ad &&
54 test_commit other &&
55
56 git rev-list --objects --no-object-names packed.. >objects &&
57 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
58 other="$(git pack-objects --delta-base-offset \
59 $packdir/pack <objects)" &&
60 git prune-packed &&
61
62 test-tool chmtime --get -100 "$packdir/pack-$other.pack" >expect &&
63
64 cruft="$(git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack <<-EOF
65 $keep
66 -pack-$other.pack
67 EOF
68 )" &&
69 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw &&
70
71 cut -d" " -f2 <actual.raw | sort -u >actual &&
72
73 test_cmp expect actual
74 )
75 '
76
77 test_expect_success "unreachable cruft objects are repacked (expire $expire)" '
78 git init repo &&
79 test_when_finished "rm -fr repo" &&
80 (
81 cd repo &&
82
83 test_commit packed &&
84 git repack -Ad &&
85 test_commit other &&
86
87 git rev-list --objects --no-object-names packed.. >objects &&
88 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
89
90 cruft_a="$(echo $keep | git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack)" &&
91 git prune-packed &&
92 cruft_b="$(git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack <<-EOF
93 $keep
94 -pack-$cruft_a.pack
95 EOF
96 )" &&
97
98 test-tool pack-mtimes "pack-$cruft_a.mtimes" >expect.raw &&
99 test-tool pack-mtimes "pack-$cruft_b.mtimes" >actual.raw &&
100
101 sort <expect.raw >expect &&
102 sort <actual.raw >actual &&
103
104 test_cmp expect actual
105 )
106 '
107
108 test_expect_success "multiple cruft packs (expire $expire)" '
109 git init repo &&
110 test_when_finished "rm -fr repo" &&
111 (
112 cd repo &&
113
114 test_commit reachable &&
115 git repack -Ad &&
116 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
117
118 test_commit cruft &&
119 loose="$objdir/$(test_oid_to_path $(git rev-parse cruft))" &&
120
121 # generate three copies of the cruft object in different
122 # cruft packs, each with a unique mtime:
123 # - one expired (1000 seconds ago)
124 # - two non-expired (one 1000 seconds in the future,
125 # one 1500 seconds in the future)
126 test-tool chmtime =-1000 "$loose" &&
127 git pack-objects --cruft $packdir/pack-A <<-EOF &&
128 $keep
129 EOF
130 test-tool chmtime =+1000 "$loose" &&
131 git pack-objects --cruft $packdir/pack-B <<-EOF &&
132 $keep
133 -$(basename $(ls $packdir/pack-A-*.pack))
134 EOF
135 test-tool chmtime =+1500 "$loose" &&
136 git pack-objects --cruft $packdir/pack-C <<-EOF &&
137 $keep
138 -$(basename $(ls $packdir/pack-A-*.pack))
139 -$(basename $(ls $packdir/pack-B-*.pack))
140 EOF
141
142 # ensure the resulting cruft pack takes the most recent
143 # mtime among all copies
144 cruft="$(git pack-objects --cruft \
145 --cruft-expiration="$expire" \
146 $packdir/pack <<-EOF
147 $keep
148 -$(basename $(ls $packdir/pack-A-*.pack))
149 -$(basename $(ls $packdir/pack-B-*.pack))
150 -$(basename $(ls $packdir/pack-C-*.pack))
151 EOF
152 )" &&
153
154 test-tool pack-mtimes "$(basename $(ls $packdir/pack-C-*.mtimes))" >expect.raw &&
155 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw &&
156
157 sort expect.raw >expect &&
158 sort actual.raw >actual &&
159 test_cmp expect actual
160 )
161 '
162
163 test_expect_success "cruft packs tolerate missing trees (expire $expire)" '
164 git init repo &&
165 test_when_finished "rm -fr repo" &&
166 (
167 cd repo &&
168
169 test_commit reachable &&
170 test_commit cruft &&
171
172 tree="$(git rev-parse cruft^{tree})" &&
173
174 git reset --hard reachable &&
175 git tag -d cruft &&
176 git reflog expire --all --expire=all &&
177
178 # remove the unreachable tree, but leave the commit
179 # which has it as its root tree intact
180 rm -fr "$objdir/$(test_oid_to_path "$tree")" &&
181
182 git repack -Ad &&
183 basename $(ls $packdir/pack-*.pack) >in &&
184 git pack-objects --cruft --cruft-expiration="$expire" \
185 $packdir/pack <in
186 )
187 '
188
189 test_expect_success "cruft packs tolerate missing blobs (expire $expire)" '
190 git init repo &&
191 test_when_finished "rm -fr repo" &&
192 (
193 cd repo &&
194
195 test_commit reachable &&
196 test_commit cruft &&
197
198 blob="$(git rev-parse cruft:cruft.t)" &&
199
200 git reset --hard reachable &&
201 git tag -d cruft &&
202 git reflog expire --all --expire=all &&
203
204 # remove the unreachable blob, but leave the commit (and
205 # the root tree of that commit) intact
206 rm -fr "$objdir/$(test_oid_to_path "$blob")" &&
207
208 git repack -Ad &&
209 basename $(ls $packdir/pack-*.pack) >in &&
210 git pack-objects --cruft --cruft-expiration="$expire" \
211 $packdir/pack <in
212 )
213 '
214 }
215
216 basic_cruft_pack_tests never
217 basic_cruft_pack_tests 2.weeks.ago
218
219 test_expect_success 'cruft tags rescue tagged objects' '
220 git init repo &&
221 test_when_finished "rm -fr repo" &&
222 (
223 cd repo &&
224
225 test_commit packed &&
226 git repack -Ad &&
227
228 test_commit tagged &&
229 git tag -a annotated -m tag &&
230
231 git rev-list --objects --no-object-names packed.. >objects &&
232 while read oid
233 do
234 test-tool chmtime -1000 \
235 "$objdir/$(test_oid_to_path $oid)"
236 done <objects &&
237
238 test-tool chmtime -500 \
239 "$objdir/$(test_oid_to_path $(git rev-parse annotated))" &&
240
241 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
242 cruft="$(echo $keep | git pack-objects --cruft \
243 --cruft-expiration=750.seconds.ago \
244 $packdir/pack)" &&
245 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw &&
246 cut -f1 -d" " <actual.raw | sort >actual &&
247
248 (
249 cat objects &&
250 git rev-parse annotated
251 ) >expect.raw &&
252 sort <expect.raw >expect &&
253
254 test_cmp expect actual &&
255 cat actual
256 )
257 '
258
259 test_expect_success 'cruft commits rescue parents, trees' '
260 git init repo &&
261 test_when_finished "rm -fr repo" &&
262 (
263 cd repo &&
264
265 test_commit packed &&
266 git repack -Ad &&
267
268 test_commit old &&
269 test_commit new &&
270
271 git rev-list --objects --no-object-names packed..new >objects &&
272 while read object
273 do
274 test-tool chmtime -1000 \
275 "$objdir/$(test_oid_to_path $object)"
276 done <objects &&
277 test-tool chmtime +500 "$objdir/$(test_oid_to_path \
278 $(git rev-parse HEAD))" &&
279
280 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
281 cruft="$(echo $keep | git pack-objects --cruft \
282 --cruft-expiration=750.seconds.ago \
283 $packdir/pack)" &&
284 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw &&
285
286 cut -d" " -f1 <actual.raw | sort >actual &&
287 sort <objects >expect &&
288
289 test_cmp expect actual
290 )
291 '
292
293 test_expect_success 'cruft trees rescue sub-trees, blobs' '
294 git init repo &&
295 test_when_finished "rm -fr repo" &&
296 (
297 cd repo &&
298
299 test_commit packed &&
300 git repack -Ad &&
301
302 mkdir -p dir/sub &&
303 echo foo >foo &&
304 echo bar >dir/bar &&
305 echo baz >dir/sub/baz &&
306
307 test_tick &&
308 git add . &&
309 git commit -m "pruned" &&
310
311 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD))" &&
312 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD^{tree}))" &&
313 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:foo))" &&
314 test-tool chmtime -500 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir))" &&
315 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir/bar))" &&
316 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir/sub))" &&
317 test-tool chmtime -1000 "$objdir/$(test_oid_to_path $(git rev-parse HEAD:dir/sub/baz))" &&
318
319 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
320 cruft="$(echo $keep | git pack-objects --cruft \
321 --cruft-expiration=750.seconds.ago \
322 $packdir/pack)" &&
323 test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw &&
324 cut -f1 -d" " <actual.raw | sort >actual &&
325
326 git rev-parse HEAD:dir HEAD:dir/bar HEAD:dir/sub HEAD:dir/sub/baz >expect.raw &&
327 sort <expect.raw >expect &&
328
329 test_cmp expect actual
330 )
331 '
332
333 test_expect_success 'expired objects are pruned' '
334 git init repo &&
335 test_when_finished "rm -fr repo" &&
336 (
337 cd repo &&
338
339 test_commit packed &&
340 git repack -Ad &&
341
342 test_commit pruned &&
343
344 git rev-list --objects --no-object-names packed..pruned >objects &&
345 while read object
346 do
347 test-tool chmtime -1000 \
348 "$objdir/$(test_oid_to_path $object)"
349 done <objects &&
350
351 keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
352 cruft="$(echo $keep | git pack-objects --cruft \
353 --cruft-expiration=750.seconds.ago \
354 $packdir/pack)" &&
355
356 test-tool pack-mtimes "pack-$cruft.mtimes" >actual &&
357 test_must_be_empty actual
358 )
359 '
360
361 test_expect_success 'repack --cruft generates a cruft pack' '
362 git init repo &&
363 test_when_finished "rm -fr repo" &&
364 (
365 cd repo &&
366
367 test_commit reachable &&
368 git branch -M main &&
369 git checkout --orphan other &&
370 test_commit unreachable &&
371
372 git checkout main &&
373 git branch -D other &&
374 git tag -d unreachable &&
375 # objects are not cruft if they are contained in the reflogs
376 git reflog expire --all --expire=all &&
377
378 git rev-list --objects --all --no-object-names >reachable.raw &&
379 git cat-file --batch-all-objects --batch-check="%(objectname)" >objects &&
380 sort <reachable.raw >reachable &&
381 comm -13 reachable objects >unreachable &&
382
383 git repack --cruft -d &&
384
385 cruft=$(basename $(ls $packdir/pack-*.mtimes) .mtimes) &&
386 pack=$(basename $(ls $packdir/pack-*.pack | grep -v $cruft) .pack) &&
387
388 git show-index <$packdir/$pack.idx >actual.raw &&
389 cut -f2 -d" " actual.raw | sort >actual &&
390 test_cmp reachable actual &&
391
392 git show-index <$packdir/$cruft.idx >actual.raw &&
393 cut -f2 -d" " actual.raw | sort >actual &&
394 test_cmp unreachable actual
395 )
396 '
397
398 test_expect_success 'loose objects mtimes upsert others' '
399 git init repo &&
400 test_when_finished "rm -fr repo" &&
401 (
402 cd repo &&
403
404 test_commit reachable &&
405 git repack -Ad &&
406 git branch -M main &&
407
408 git checkout --orphan other &&
409 test_commit cruft &&
410 # incremental repack, leaving existing objects loose (so
411 # they can be "freshened")
412 git repack &&
413
414 tip="$(git rev-parse cruft)" &&
415 path="$objdir/$(test_oid_to_path "$tip")" &&
416 test-tool chmtime --get +1000 "$path" >expect &&
417
418 git checkout main &&
419 git branch -D other &&
420 git tag -d cruft &&
421 git reflog expire --all --expire=all &&
422
423 git repack --cruft -d &&
424
425 mtimes="$(basename $(ls $packdir/pack-*.mtimes))" &&
426 test-tool pack-mtimes "$mtimes" >actual.raw &&
427 grep "$tip" actual.raw | cut -d" " -f2 >actual &&
428 test_cmp expect actual
429 )
430 '
431
432 test_expect_success 'expiring cruft objects with git gc' '
433 git init repo &&
434 test_when_finished "rm -fr repo" &&
435 (
436 cd repo &&
437
438 test_commit reachable &&
439 git branch -M main &&
440 git checkout --orphan other &&
441 test_commit unreachable &&
442
443 git checkout main &&
444 git branch -D other &&
445 git tag -d unreachable &&
446 # objects are not cruft if they are contained in the reflogs
447 git reflog expire --all --expire=all &&
448
449 git rev-list --objects --all --no-object-names >reachable.raw &&
450 git cat-file --batch-all-objects --batch-check="%(objectname)" >objects &&
451 sort <reachable.raw >reachable &&
452 comm -13 reachable objects >unreachable &&
453
454 # Write a cruft pack containing all unreachable objects.
455 git gc --cruft --prune="01-01-1980" &&
456
457 mtimes=$(ls .git/objects/pack/pack-*.mtimes) &&
458 test_path_is_file $mtimes &&
459
460 # Prune all unreachable objects from the cruft pack.
461 git gc --cruft --prune=now &&
462
463 git cat-file --batch-all-objects --batch-check="%(objectname)" >objects &&
464
465 comm -23 unreachable objects >removed &&
466 test_cmp unreachable removed &&
467 test_path_is_missing $mtimes
468 )
469 '
470
471 test_expect_success 'cruft packs are not included in geometric repack' '
472 git init repo &&
473 test_when_finished "rm -fr repo" &&
474 (
475 cd repo &&
476
477 test_commit reachable &&
478 git repack -Ad &&
479 git branch -M main &&
480
481 git checkout --orphan other &&
482 test_commit cruft &&
483 git repack -d &&
484
485 git checkout main &&
486 git branch -D other &&
487 git tag -d cruft &&
488 git reflog expire --all --expire=all &&
489
490 git repack --cruft &&
491
492 find $packdir -type f | sort >before &&
493 git repack --geometric=2 -d &&
494 find $packdir -type f | sort >after &&
495
496 test_cmp before after
497 )
498 '
499
500 test_expect_success 'repack --geometric collects once-cruft objects' '
501 git init repo &&
502 test_when_finished "rm -fr repo" &&
503 (
504 cd repo &&
505
506 test_commit reachable &&
507 git repack -Ad &&
508 git branch -M main &&
509
510 git checkout --orphan other &&
511 git rm -rf . &&
512 test_commit --no-tag cruft &&
513 cruft="$(git rev-parse HEAD)" &&
514
515 git checkout main &&
516 git branch -D other &&
517 git reflog expire --all --expire=all &&
518
519 # Pack the objects created in the previous step into a cruft
520 # pack. Intentionally leave loose copies of those objects
521 # around so we can pick them up in a subsequent --geometric
522 # reapack.
523 git repack --cruft &&
524
525 # Now make those objects reachable, and ensure that they are
526 # packed into the new pack created via a --geometric repack.
527 git update-ref refs/heads/other $cruft &&
528
529 # Without this object, the set of unpacked objects is exactly
530 # the set of objects already in the cruft pack. Tweak that set
531 # to ensure we do not overwrite the cruft pack entirely.
532 test_commit reachable2 &&
533
534 find $packdir -name "pack-*.idx" | sort >before &&
535 git repack --geometric=2 -d &&
536 find $packdir -name "pack-*.idx" | sort >after &&
537
538 {
539 git rev-list --objects --no-object-names $cruft &&
540 git rev-list --objects --no-object-names reachable..reachable2
541 } >want.raw &&
542 sort want.raw >want &&
543
544 pack=$(comm -13 before after) &&
545 git show-index <$pack >objects.raw &&
546
547 cut -d" " -f2 objects.raw | sort >got &&
548
549 test_cmp want got
550 )
551 '
552
553 test_expect_success 'cruft repack with no reachable objects' '
554 git init repo &&
555 test_when_finished "rm -fr repo" &&
556 (
557 cd repo &&
558
559 test_commit base &&
560 git repack -ad &&
561
562 base="$(git rev-parse base)" &&
563
564 git for-each-ref --format="delete %(refname)" >in &&
565 git update-ref --stdin <in &&
566 git reflog expire --all --expire=all &&
567 rm -fr .git/index &&
568
569 git repack --cruft -d &&
570
571 git cat-file -t $base
572 )
573 '
574
575 test_expect_success 'cruft repack ignores --max-pack-size' '
576 git init max-pack-size &&
577 (
578 cd max-pack-size &&
579 test_commit base &&
580 # two cruft objects which exceed the maximum pack size
581 test-tool genrandom foo 1048576 | git hash-object --stdin -w &&
582 test-tool genrandom bar 1048576 | git hash-object --stdin -w &&
583 git repack --cruft --max-pack-size=1M &&
584 find $packdir -name "*.mtimes" >cruft &&
585 test_line_count = 1 cruft &&
586 test-tool pack-mtimes "$(basename "$(cat cruft)")" >objects &&
587 test_line_count = 2 objects
588 )
589 '
590
591 test_expect_success 'cruft repack ignores pack.packSizeLimit' '
592 (
593 cd max-pack-size &&
594 # repack everything back together to remove the existing cruft
595 # pack (but to keep its objects)
596 git repack -adk &&
597 git -c pack.packSizeLimit=1M repack --cruft &&
598 # ensure the same post condition is met when --max-pack-size
599 # would otherwise be inferred from the configuration
600 find $packdir -name "*.mtimes" >cruft &&
601 test_line_count = 1 cruft &&
602 test-tool pack-mtimes "$(basename "$(cat cruft)")" >objects &&
603 test_line_count = 2 objects
604 )
605 '
606
607 test_expect_success 'cruft repack respects repack.cruftWindow' '
608 git init repo &&
609 test_when_finished "rm -fr repo" &&
610 (
611 cd repo &&
612
613 test_commit base &&
614
615 GIT_TRACE2_EVENT=$(pwd)/event.trace \
616 git -c pack.window=1 -c repack.cruftWindow=2 repack \
617 --cruft --window=3 &&
618
619 grep "pack-objects.*--window=2.*--cruft" event.trace
620 )
621 '
622
623 test_expect_success 'cruft repack respects --window by default' '
624 git init repo &&
625 test_when_finished "rm -fr repo" &&
626 (
627 cd repo &&
628
629 test_commit base &&
630
631 GIT_TRACE2_EVENT=$(pwd)/event.trace \
632 git -c pack.window=2 repack --cruft --window=3 &&
633
634 grep "pack-objects.*--window=3.*--cruft" event.trace
635 )
636 '
637
638 test_expect_success 'cruft repack respects --quiet' '
639 git init repo &&
640 test_when_finished "rm -fr repo" &&
641 (
642 cd repo &&
643
644 test_commit base &&
645 GIT_PROGRESS_DELAY=0 git repack --cruft --quiet 2>err &&
646 test_must_be_empty err
647 )
648 '
649
650 test_expect_success 'cruft --local drops unreachable objects' '
651 git init alternate &&
652 git init repo &&
653 test_when_finished "rm -fr alternate repo" &&
654
655 test_commit -C alternate base &&
656 # Pack all objects in alterate so that the cruft repack in "repo" sees
657 # the object it dropped due to `--local` as packed. Otherwise this
658 # object would not appear packed anywhere (since it is not packed in
659 # alternate and likewise not part of the cruft pack in the other repo
660 # because of `--local`).
661 git -C alternate repack -ad &&
662
663 (
664 cd repo &&
665
666 object="$(git -C ../alternate rev-parse HEAD:base.t)" &&
667 git -C ../alternate cat-file -p $object >contents &&
668
669 # Write some reachable objects and two unreachable ones: one
670 # that the alternate has and another that is unique.
671 test_commit other &&
672 git hash-object -w -t blob contents &&
673 cruft="$(echo cruft | git hash-object -w -t blob --stdin)" &&
674
675 ( cd ../alternate/.git/objects && pwd ) \
676 >.git/objects/info/alternates &&
677
678 test_path_is_file $objdir/$(test_oid_to_path $cruft) &&
679 test_path_is_file $objdir/$(test_oid_to_path $object) &&
680
681 git repack -d --cruft --local &&
682
683 test-tool pack-mtimes "$(basename $(ls $packdir/pack-*.mtimes))" \
684 >objects &&
685 ! grep $object objects &&
686 grep $cruft objects
687 )
688 '
689
690 test_expect_success 'MIDX bitmaps tolerate reachable cruft objects' '
691 git init repo &&
692 test_when_finished "rm -fr repo" &&
693 (
694 cd repo &&
695
696 test_commit reachable &&
697 test_commit cruft &&
698 unreachable="$(git rev-parse cruft)" &&
699
700 git reset --hard $unreachable^ &&
701 git tag -d cruft &&
702 git reflog expire --all --expire=all &&
703
704 git repack --cruft -d &&
705
706 # resurrect the unreachable object via a new commit. the
707 # new commit will get selected for a bitmap, but be
708 # missing one of its parents from the selected packs.
709 git reset --hard $unreachable &&
710 test_commit resurrect &&
711
712 git repack --write-midx --write-bitmap-index --geometric=2 -d
713 )
714 '
715
716 test_expect_success 'cruft objects are freshend via loose' '
717 git init repo &&
718 test_when_finished "rm -fr repo" &&
719 (
720 cd repo &&
721
722 echo "cruft" >contents &&
723 blob="$(git hash-object -w -t blob contents)" &&
724 loose="$objdir/$(test_oid_to_path $blob)" &&
725
726 test_commit base &&
727
728 git repack --cruft -d &&
729
730 test_path_is_missing "$loose" &&
731 test-tool pack-mtimes "$(basename "$(ls $packdir/pack-*.mtimes)")" >cruft &&
732 grep "$blob" cruft &&
733
734 # write the same object again
735 git hash-object -w -t blob contents &&
736
737 test_path_is_file "$loose"
738 )
739 '
740
741 test_done