|  | #!/bin/sh | 
|  |  | 
|  | test_description=' | 
|  | Test pruning of repositories with minor corruptions. The goal | 
|  | here is that we should always be erring on the side of safety. So | 
|  | if we see, for example, a ref with a bogus name, it is OK either to | 
|  | bail out or to proceed using it as a reachable tip, but it is _not_ | 
|  | OK to proceed as if it did not exist. Otherwise we might silently | 
|  | delete objects that cannot be recovered. | 
|  | ' | 
|  | . ./test-lib.sh | 
|  |  | 
|  | test_expect_success 'disable reflogs' ' | 
|  | git config core.logallrefupdates false && | 
|  | git reflog expire --expire=all --all | 
|  | ' | 
|  |  | 
|  | test_expect_success 'create history reachable only from a bogus-named ref' ' | 
|  | test_tick && git commit --allow-empty -m master && | 
|  | base=$(git rev-parse HEAD) && | 
|  | test_tick && git commit --allow-empty -m bogus && | 
|  | bogus=$(git rev-parse HEAD) && | 
|  | git cat-file commit $bogus >saved && | 
|  | echo $bogus >.git/refs/heads/bogus..name && | 
|  | git reset --hard HEAD^ | 
|  | ' | 
|  |  | 
|  | test_expect_success 'pruning does not drop bogus object' ' | 
|  | test_when_finished "git hash-object -w -t commit saved" && | 
|  | test_might_fail git prune --expire=now && | 
|  | verbose git cat-file -e $bogus | 
|  | ' | 
|  |  | 
|  | test_expect_success 'put bogus object into pack' ' | 
|  | git tag reachable $bogus && | 
|  | git repack -ad && | 
|  | git tag -d reachable && | 
|  | verbose git cat-file -e $bogus | 
|  | ' | 
|  |  | 
|  | test_expect_success 'destructive repack keeps packed object' ' | 
|  | test_might_fail git repack -Ad --unpack-unreachable=now && | 
|  | verbose git cat-file -e $bogus && | 
|  | test_might_fail git repack -ad && | 
|  | verbose git cat-file -e $bogus | 
|  | ' | 
|  |  | 
|  | # subsequent tests will have different corruptions | 
|  | test_expect_success 'clean up bogus ref' ' | 
|  | rm .git/refs/heads/bogus..name | 
|  | ' | 
|  |  | 
|  | # We create two new objects here, "one" and "two". Our | 
|  | # master branch points to "two", which is deleted, | 
|  | # corrupting the repository. But we'd like to make sure | 
|  | # that the otherwise unreachable "one" is not pruned | 
|  | # (since it is the user's best bet for recovering | 
|  | # from the corruption). | 
|  | # | 
|  | # Note that we also point HEAD somewhere besides "two", | 
|  | # as we want to make sure we test the case where we | 
|  | # pick up the reference to "two" by iterating the refs, | 
|  | # not by resolving HEAD. | 
|  | test_expect_success 'create history with missing tip commit' ' | 
|  | test_tick && git commit --allow-empty -m one && | 
|  | recoverable=$(git rev-parse HEAD) && | 
|  | git cat-file commit $recoverable >saved && | 
|  | test_tick && git commit --allow-empty -m two && | 
|  | missing=$(git rev-parse HEAD) && | 
|  | git checkout --detach $base && | 
|  | rm .git/objects/$(echo $missing | sed "s,..,&/,") && | 
|  | test_must_fail git cat-file -e $missing | 
|  | ' | 
|  |  | 
|  | test_expect_success 'pruning with a corrupted tip does not drop history' ' | 
|  | test_when_finished "git hash-object -w -t commit saved" && | 
|  | test_might_fail git prune --expire=now && | 
|  | verbose git cat-file -e $recoverable | 
|  | ' | 
|  |  | 
|  | test_expect_success 'pack-refs does not silently delete broken loose ref' ' | 
|  | git pack-refs --all --prune && | 
|  | echo $missing >expect && | 
|  | git rev-parse refs/heads/master >actual && | 
|  | test_cmp expect actual | 
|  | ' | 
|  |  | 
|  | # we do not want to count on running pack-refs to | 
|  | # actually pack it, as it is perfectly reasonable to | 
|  | # skip processing a broken ref | 
|  | test_expect_success 'create packed-refs file with broken ref' ' | 
|  | rm -f .git/refs/heads/master && | 
|  | cat >.git/packed-refs <<-EOF && | 
|  | $missing refs/heads/master | 
|  | $recoverable refs/heads/other | 
|  | EOF | 
|  | echo $missing >expect && | 
|  | git rev-parse refs/heads/master >actual && | 
|  | test_cmp expect actual | 
|  | ' | 
|  |  | 
|  | test_expect_success 'pack-refs does not silently delete broken packed ref' ' | 
|  | git pack-refs --all --prune && | 
|  | git rev-parse refs/heads/master >actual && | 
|  | test_cmp expect actual | 
|  | ' | 
|  |  | 
|  | test_expect_success 'pack-refs does not drop broken refs during deletion' ' | 
|  | git update-ref -d refs/heads/other && | 
|  | git rev-parse refs/heads/master >actual && | 
|  | test_cmp expect actual | 
|  | ' | 
|  |  | 
|  | test_done |