( cd C && git fsck )
'
+test_expect_success 'setup repo with garbage in objects/*' '
+ git init S &&
+ (
+ cd S &&
+ test_commit A &&
+
+ cd .git/objects &&
+ >.some-hidden-file &&
+ >some-file &&
+ mkdir .some-hidden-dir &&
+ >.some-hidden-dir/some-file &&
+ >.some-hidden-dir/.some-dot-file &&
+ mkdir some-dir &&
+ >some-dir/some-file &&
+ >some-dir/.some-dot-file
+ )
+'
+
+test_expect_success 'clone a repo with garbage in objects/*' '
+ for option in --local --no-hardlinks --shared --dissociate
+ do
+ git clone $option S S$option || return 1 &&
+ git -C S$option fsck || return 1
+ done &&
+ find S-* -name "*some*" | sort >actual &&
+ cat >expected <<-EOF &&
+ S--dissociate/.git/objects/.some-hidden-dir
+ S--dissociate/.git/objects/.some-hidden-dir/.some-dot-file
+ S--dissociate/.git/objects/.some-hidden-dir/some-file
+ S--dissociate/.git/objects/.some-hidden-file
+ S--dissociate/.git/objects/some-dir
+ S--dissociate/.git/objects/some-dir/.some-dot-file
+ S--dissociate/.git/objects/some-dir/some-file
+ S--dissociate/.git/objects/some-file
+ S--local/.git/objects/.some-hidden-dir
+ S--local/.git/objects/.some-hidden-dir/.some-dot-file
+ S--local/.git/objects/.some-hidden-dir/some-file
+ S--local/.git/objects/.some-hidden-file
+ S--local/.git/objects/some-dir
+ S--local/.git/objects/some-dir/.some-dot-file
+ S--local/.git/objects/some-dir/some-file
+ S--local/.git/objects/some-file
+ S--no-hardlinks/.git/objects/.some-hidden-dir
+ S--no-hardlinks/.git/objects/.some-hidden-dir/.some-dot-file
+ S--no-hardlinks/.git/objects/.some-hidden-dir/some-file
+ S--no-hardlinks/.git/objects/.some-hidden-file
+ S--no-hardlinks/.git/objects/some-dir
+ S--no-hardlinks/.git/objects/some-dir/.some-dot-file
+ S--no-hardlinks/.git/objects/some-dir/some-file
+ S--no-hardlinks/.git/objects/some-file
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success SYMLINKS 'setup repo with manually symlinked or unknown files at objects/' '
+ git init T &&
+ (
+ cd T &&
+ git config gc.auto 0 &&
+ test_commit A &&
+ git gc &&
+ test_commit B &&
+
+ cd .git/objects &&
+ mv pack packs &&
+ ln -s packs pack &&
+ find ?? -type d >loose-dirs &&
+ last_loose=$(tail -n 1 loose-dirs) &&
+ mv $last_loose a-loose-dir &&
+ ln -s a-loose-dir $last_loose &&
+ first_loose=$(head -n 1 loose-dirs) &&
+ rm -f loose-dirs &&
+
+ cd $first_loose &&
+ obj=$(ls *) &&
+ mv $obj ../an-object &&
+ ln -s ../an-object $obj &&
+
+ cd ../ &&
+ find . -type f | sort >../../../T.objects-files.raw &&
+ find . -type l | sort >../../../T.objects-symlinks.raw &&
+ echo unknown_content >unknown_file
+ ) &&
+ git -C T fsck &&
+ git -C T rev-list --all --objects >T.objects
+'
+
+
+test_expect_success SYMLINKS 'clone repo with symlinked or unknown files at objects/' '
+ for option in --local --no-hardlinks --shared --dissociate
+ do
+ git clone $option T T$option || return 1 &&
+ git -C T$option fsck || return 1 &&
+ git -C T$option rev-list --all --objects >T$option.objects &&
+ test_cmp T.objects T$option.objects &&
+ (
+ cd T$option/.git/objects &&
+ find . -type f | sort >../../../T$option.objects-files.raw &&
+ find . -type l | sort >../../../T$option.objects-symlinks.raw
+ )
+ done &&
+
+ for raw in $(ls T*.raw)
+ do
+ sed -e "s!/../!/Y/!; s![0-9a-f]\{38,\}!Z!" -e "/commit-graph/d" \
+ -e "/multi-pack-index/d" <$raw >$raw.de-sha || return 1
+ done &&
+
+ cat >expected-files <<-EOF &&
+ ./Y/Z
+ ./Y/Z
+ ./a-loose-dir/Z
+ ./an-object
+ ./Y/Z
+ ./info/packs
+ ./pack/pack-Z.idx
+ ./pack/pack-Z.pack
+ ./packs/pack-Z.idx
+ ./packs/pack-Z.pack
+ ./unknown_file
+ EOF
+
+ for option in --local --no-hardlinks --dissociate
+ do
+ test_cmp expected-files T$option.objects-files.raw.de-sha || return 1 &&
+ test_must_be_empty T$option.objects-symlinks.raw.de-sha || return 1
+ done &&
+
+ echo ./info/alternates >expected-files &&
+ test_cmp expected-files T--shared.objects-files.raw &&
+ test_must_be_empty T--shared.objects-symlinks.raw
+'
+
test_done