#!/bin/sh global test_description := ''see how we handle various forms of corruption'' source ./test-lib.sh # convert "1234abcd" to ".git/objects/12/34abcd" proc obj_to_file { echo "$[git rev-parse --git-dir]/objects/$[git rev-parse $1 | sed 's,..,&/,]" } # Convert byte at offset "$2" of object "$1" into '\0' proc corrupt_byte { global obj_file := $[obj_to_file $1] && chmod +w $obj_file && printf '\0' | dd of="$obj_file" bs=1 seek="$2" conv=notrunc } test_expect_success 'setup corrupt repo' ' git init bit-error && ( cd bit-error && test_commit content && corrupt_byte HEAD:content.t 10 ) ' test_expect_success 'setup repo with missing object' ' git init missing && ( cd missing && test_commit content && rm -f "$(obj_to_file HEAD:content.t)" ) ' test_expect_success 'setup repo with misnamed object' ' git init misnamed && ( cd misnamed && test_commit content && good=$(obj_to_file HEAD:content.t) && blob=$(echo corrupt | git hash-object -w --stdin) && bad=$(obj_to_file $blob) && rm -f "$good" && mv "$bad" "$good" ) ' test_expect_success 'streaming a corrupt blob fails' ' ( cd bit-error && test_must_fail git cat-file blob HEAD:content.t ) ' test_expect_success 'read-tree -u detects bit-errors in blobs' ' ( cd bit-error && rm -f content.t && test_must_fail git read-tree --reset -u HEAD ) ' test_expect_success 'read-tree -u detects missing objects' ' ( cd missing && rm -f content.t && test_must_fail git read-tree --reset -u HEAD ) ' # We use --bare to make sure that the transport detects it, not the checkout # phase. test_expect_success 'clone --no-local --bare detects corruption' ' test_must_fail git clone --no-local --bare bit-error corrupt-transport ' test_expect_success 'clone --no-local --bare detects missing object' ' test_must_fail git clone --no-local --bare missing missing-transport ' test_expect_success 'clone --no-local --bare detects misnamed object' ' test_must_fail git clone --no-local --bare misnamed misnamed-transport ' # We do not expect --local to detect corruption at the transport layer, # so we are really checking the checkout() code path. test_expect_success 'clone --local detects corruption' ' test_must_fail git clone --local bit-error corrupt-checkout ' test_expect_success 'error detected during checkout leaves repo intact' ' test_path_is_dir corrupt-checkout/.git ' test_expect_success 'clone --local detects missing objects' ' test_must_fail git clone --local missing missing-checkout ' test_expect_failure 'clone --local detects misnamed objects' ' test_must_fail git clone --local misnamed misnamed-checkout ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"see how we handle various forms of corruption">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (FuncDef name: obj_to_file body: (BraceGroup children: [ (C {(echo)} { (DQ (CommandSubPart command_list: (CommandList children:[(C {(git)} {(rev-parse)} {(--git-dir)})]) left_token: spids: [27 33] ) (/objects/) (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(git)} {(rev-parse)} {(DQ ($ VSub_Number "$1"))}) (C {(sed)} {(SQ <"s,..,&/,">)}) ] negated: False ) ] ) left_token: spids: [35 51] ) ) } ) ] spids: [21] ) spids: [17 20] ) (FuncDef name: corrupt_byte body: (BraceGroup children: [ (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:obj_file) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(obj_to_file)} {(DQ ($ VSub_Number "$1"))})] ) left_token: spids: [68 74] ) } spids: [67] ) ] spids: [67] ) (AndOr children: [ (C {(chmod)} {(Lit_Other "+") (w)} {(DQ ($ VSub_Name "$obj_file"))}) (Pipeline children: [ (C {(printf)} {(SQ <"\\0">)}) (C {(dd)} {(Lit_VarLike "of=") (DQ ($ VSub_Name "$obj_file"))} {(Lit_VarLike "bs=") (1)} {(Lit_VarLike "seek=") (DQ ($ VSub_Number "$2"))} {(Lit_VarLike "conv=") (notrunc)} ) ] negated: False ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [64] ) spids: [60 63] ) (C {(test_expect_success)} {(SQ <"setup corrupt repo">)} { (SQ <"\n"> <"\tgit init bit-error &&\n"> <"\t(\n"> <"\t\tcd bit-error &&\n"> <"\t\ttest_commit content &&\n"> <"\t\tcorrupt_byte HEAD:content.t 10\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup repo with missing object">)} { (SQ <"\n"> <"\tgit init missing &&\n"> <"\t(\n"> <"\t\tcd missing &&\n"> <"\t\ttest_commit content &&\n"> <"\t\trm -f \"$(obj_to_file HEAD:content.t)\"\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup repo with misnamed object">)} { (SQ <"\n"> <"\tgit init misnamed &&\n"> <"\t(\n"> <"\t\tcd misnamed &&\n"> <"\t\ttest_commit content &&\n"> <"\t\tgood=$(obj_to_file HEAD:content.t) &&\n"> <"\t\tblob=$(echo corrupt | git hash-object -w --stdin) &&\n"> <"\t\tbad=$(obj_to_file $blob) &&\n"> <"\t\trm -f \"$good\" &&\n"> <"\t\tmv \"$bad\" \"$good\"\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"streaming a corrupt blob fails">)} { (SQ <"\n"> <"\t(\n"> <"\t\tcd bit-error &&\n"> <"\t\ttest_must_fail git cat-file blob HEAD:content.t\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree -u detects bit-errors in blobs">)} { (SQ <"\n"> <"\t(\n"> <"\t\tcd bit-error &&\n"> <"\t\trm -f content.t &&\n"> <"\t\ttest_must_fail git read-tree --reset -u HEAD\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"read-tree -u detects missing objects">)} { (SQ <"\n"> <"\t(\n"> <"\t\tcd missing &&\n"> <"\t\trm -f content.t &&\n"> <"\t\ttest_must_fail git read-tree --reset -u HEAD\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"clone --no-local --bare detects corruption">)} {(SQ <"\n"> <"\ttest_must_fail git clone --no-local --bare bit-error corrupt-transport\n">)} ) (C {(test_expect_success)} {(SQ <"clone --no-local --bare detects missing object">)} {(SQ <"\n"> <"\ttest_must_fail git clone --no-local --bare missing missing-transport\n">)} ) (C {(test_expect_success)} {(SQ <"clone --no-local --bare detects misnamed object">)} {(SQ <"\n"> <"\ttest_must_fail git clone --no-local --bare misnamed misnamed-transport\n">)} ) (C {(test_expect_success)} {(SQ <"clone --local detects corruption">)} {(SQ <"\n"> <"\ttest_must_fail git clone --local bit-error corrupt-checkout\n">)} ) (C {(test_expect_success)} {(SQ <"error detected during checkout leaves repo intact">)} {(SQ <"\n"> <"\ttest_path_is_dir corrupt-checkout/.git\n">)} ) (C {(test_expect_success)} {(SQ <"clone --local detects missing objects">)} {(SQ <"\n"> <"\ttest_must_fail git clone --local missing missing-checkout\n">)} ) (C {(test_expect_failure)} {(SQ <"clone --local detects misnamed objects">)} {(SQ <"\n"> <"\ttest_must_fail git clone --local misnamed misnamed-checkout\n">)} ) (C {(test_done)}) ] )