Merge branch 'jk/fsck-connectivity-check-fix'
authorJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:15:01 +0000 (13:15 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:15:01 +0000 (13:15 -0800)
"git fsck --connectivity-check" was not working at all.

* jk/fsck-connectivity-check-fix:
fsck: lazily load types under --connectivity-only
fsck: move typename() printing to its own function
t1450: use "mv -f" within loose object directory
fsck: check HAS_OBJ more consistently
fsck: do not fallback "git fsck <bogus>" to "git fsck"
fsck: tighten error-checks of "git fsck <head>"
fsck: prepare dummy objects for --connectivity-check
fsck: report trees as dangling
t1450: clean up sub-objects in duplicate-entry test

1  2 
builtin/fsck.c
t/t1450-fsck.sh
diff --cc builtin/fsck.c
Simple merge
diff --cc t/t1450-fsck.sh
index 8975b4d1bcc4675be4d1869783ee4b7cc17c750f,d9cd99f2cb64f751fe8cb49065e0795bb2764ea9..33a51c9a67fe833e31e51099f7568b64be385d07
@@@ -535,6 -549,26 +549,19 @@@ test_expect_success 'fsck --connectivit
        )
  '
  
 -remove_loose_object () {
 -      sha1="$(git rev-parse "$1")" &&
 -      remainder=${sha1#??} &&
 -      firsttwo=${sha1%$remainder} &&
 -      rm .git/objects/$firsttwo/$remainder
 -}
 -
+ test_expect_success 'fsck --connectivity-only with explicit head' '
+       rm -rf connectivity-only &&
+       git init connectivity-only &&
+       (
+               cd connectivity-only &&
+               test_commit foo &&
+               rm -f .git/index &&
+               tree=$(git rev-parse HEAD^{tree}) &&
+               remove_object $(git rev-parse HEAD:foo.t) &&
+               test_must_fail git fsck --connectivity-only $tree
+       )
+ '
  test_expect_success 'fsck --name-objects' '
        rm -rf name-objects &&
        git init name-objects &&
        )
  '
  
 +test_expect_success 'alternate objects are correctly blamed' '
 +      test_when_finished "rm -rf alt.git .git/objects/info/alternates" &&
 +      git init --bare alt.git &&
 +      echo "../../alt.git/objects" >.git/objects/info/alternates &&
 +      mkdir alt.git/objects/12 &&
 +      >alt.git/objects/12/34567890123456789012345678901234567890 &&
 +      test_must_fail git fsck >out 2>&1 &&
 +      grep alt.git out
 +'
 +
 +test_expect_success 'fsck errors in packed objects' '
 +      git cat-file commit HEAD >basis &&
 +      sed "s/</one/" basis >one &&
 +      sed "s/</foo/" basis >two &&
 +      one=$(git hash-object -t commit -w one) &&
 +      two=$(git hash-object -t commit -w two) &&
 +      pack=$(
 +              {
 +                      echo $one &&
 +                      echo $two
 +              } | git pack-objects .git/objects/pack/pack
 +      ) &&
 +      test_when_finished "rm -f .git/objects/pack/pack-$pack.*" &&
 +      remove_object $one &&
 +      remove_object $two &&
 +      test_must_fail git fsck 2>out &&
 +      grep "error in commit $one.* - bad name" out &&
 +      grep "error in commit $two.* - bad name" out &&
 +      ! grep corrupt out
 +'
 +
 +test_expect_success 'fsck finds problems in duplicate loose objects' '
 +      rm -rf broken-duplicate &&
 +      git init broken-duplicate &&
 +      (
 +              cd broken-duplicate &&
 +              test_commit duplicate &&
 +              # no "-d" here, so we end up with duplicates
 +              git repack &&
 +              # now corrupt the loose copy
 +              file=$(sha1_file "$(git rev-parse HEAD)") &&
 +              rm "$file" &&
 +              echo broken >"$file" &&
 +              test_must_fail git fsck
 +      )
 +'
 +
 +test_expect_success 'fsck detects trailing loose garbage (commit)' '
 +      git cat-file commit HEAD >basis &&
 +      echo bump-commit-sha1 >>basis &&
 +      commit=$(git hash-object -w -t commit basis) &&
 +      file=$(sha1_file $commit) &&
 +      test_when_finished "remove_object $commit" &&
 +      chmod +w "$file" &&
 +      echo garbage >>"$file" &&
 +      test_must_fail git fsck 2>out &&
 +      test_i18ngrep "garbage.*$commit" out
 +'
 +
 +test_expect_success 'fsck detects trailing loose garbage (blob)' '
 +      blob=$(echo trailing | git hash-object -w --stdin) &&
 +      file=$(sha1_file $blob) &&
 +      test_when_finished "remove_object $blob" &&
 +      chmod +w "$file" &&
 +      echo garbage >>"$file" &&
 +      test_must_fail git fsck 2>out &&
 +      test_i18ngrep "garbage.*$blob" out
 +'
 +
+ # for each of type, we have one version which is referenced by another object
+ # (and so while unreachable, not dangling), and another variant which really is
+ # dangling.
+ test_expect_success 'fsck notices dangling objects' '
+       git init dangling &&
+       (
+               cd dangling &&
+               blob=$(echo not-dangling | git hash-object -w --stdin) &&
+               dblob=$(echo dangling | git hash-object -w --stdin) &&
+               tree=$(printf "100644 blob %s\t%s\n" $blob one | git mktree) &&
+               dtree=$(printf "100644 blob %s\t%s\n" $blob two | git mktree) &&
+               commit=$(git commit-tree $tree) &&
+               dcommit=$(git commit-tree -p $commit $tree) &&
+               cat >expect <<-EOF &&
+               dangling blob $dblob
+               dangling commit $dcommit
+               dangling tree $dtree
+               EOF
+               git fsck >actual &&
+               # the output order is non-deterministic, as it comes from a hash
+               sort <actual >actual.sorted &&
+               test_cmp expect actual.sorted
+       )
+ '
+ test_expect_success 'fsck $name notices bogus $name' '
+       test_must_fail git fsck bogus &&
+       test_must_fail git fsck $_z40
+ '
+ test_expect_success 'bogus head does not fallback to all heads' '
+       # set up a case that will cause a reachability complaint
+       echo to-be-deleted >foo &&
+       git add foo &&
+       blob=$(git rev-parse :foo) &&
+       test_when_finished "git rm --cached foo" &&
+       remove_object $blob &&
+       test_must_fail git fsck $_z40 >out 2>&1 &&
+       ! grep $blob out
+ '
  test_done