(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'test_description='> name:test_description) op: assign_op.Equal rhs: {(SQ <'resilience to pack corruptions with redundant objects'>)} spids: [13] ) ] redirects: [] ) (C {<.>} {<'./test-lib.sh'>}) (command.ShFunction name: create_test_files body: (BraceGroup left: <Id.Lit_LBrace '{'> children: [ (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp] children: [ (command.Simple words: [{<test-genrandom>} {(DQ <foo>)} {<2000>}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<file_1>})] more_env: [] do_fork: T ) (command.Simple words: [{<test-genrandom>} {(DQ <foo>)} {<1800>}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<file_2>})] more_env: [] do_fork: T ) (command.Simple words: [{<test-genrandom>} {(DQ <foo>)} {<1800>}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<file_3>})] more_env: [] do_fork: T ) (command.Simple words: [{<echo>} {(DQ <' base '>)}] redirects: [(redir op:<Id.Redir_DGreat '>>'> loc:(redir_loc.Fd fd:1) arg:{<file_1>})] more_env: [] do_fork: T ) (command.Simple words: [{<echo>} {(DQ <' delta1 '>)}] redirects: [(redir op:<Id.Redir_DGreat '>>'> loc:(redir_loc.Fd fd:1) arg:{<file_2>})] more_env: [] do_fork: T ) (command.Simple words: [{<echo>} {(DQ <' delta delta2 '>)}] redirects: [(redir op:<Id.Redir_DGreat '>>'> loc:(redir_loc.Fd fd:1) arg:{<file_3>})] more_env: [] do_fork: T ) (command.Simple words: [{<test-genrandom>} {(DQ <bar>)} {<150>}] redirects: [(redir op:<Id.Redir_DGreat '>>'> loc:(redir_loc.Fd fd:1) arg:{<file_2>})] more_env: [] do_fork: T ) (command.Simple words: [{<test-genrandom>} {(DQ <baz>)} {<100>}] redirects: [(redir op:<Id.Redir_DGreat '>>'> loc:(redir_loc.Fd fd:1) arg:{<file_3>})] more_env: [] do_fork: T ) ] ) ] redirects: [] right: <Id.Lit_RBrace '}'> ) ) (command.ShFunction name: create_new_pack body: (BraceGroup left: <Id.Lit_LBrace '{'> children: [ (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp] children: [ (C {<rm>} {<-rf>} {<.git>}) (C {<git>} {<init>}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'blob_1='> name:blob_1) op: assign_op.Equal rhs: { (command_sub left_token: <Id.Left_DollarParen '$('> child: (C {<git>} {<hash-object>} {<-t>} {<blob>} {<-w>} {<file_1>}) right: <Id.Eof_RParen _> ) } spids: [201] ) ] redirects: [] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'blob_2='> name:blob_2) op: assign_op.Equal rhs: { (command_sub left_token: <Id.Left_DollarParen '$('> child: (C {<git>} {<hash-object>} {<-t>} {<blob>} {<-w>} {<file_2>}) right: <Id.Eof_RParen _> ) } spids: [219] ) ] redirects: [] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'blob_3='> name:blob_3) op: assign_op.Equal rhs: { (command_sub left_token: <Id.Left_DollarParen '$('> child: (C {<git>} {<hash-object>} {<-t>} {<blob>} {<-w>} {<file_3>}) right: <Id.Eof_RParen _> ) } spids: [237] ) ] redirects: [] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'pack='> name:pack) op: assign_op.Equal rhs: { (command_sub left_token: <Id.Left_DollarParen '$('> child: (command.Pipeline children: [ (C {<printf>} { (DQ ($ Id.VSub_DollarName blob_1) <Id.Lit_BadBackslash '\\'> <n> ($ Id.VSub_DollarName blob_2) <Id.Lit_BadBackslash '\\'> <n> ($ Id.VSub_DollarName blob_3) <Id.Lit_BadBackslash '\\'> <n> ) } ) (C {<git>} {<pack-objects>} {($ Id.VSub_At '@')} {<'.git/objects/pack/pack'>} ) ] negated: F stderr_indices: [] ) right: <Id.Eof_RParen _> ) } spids: [255] ) ] redirects: [] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'pack='> name:pack) op: assign_op.Equal rhs: {(DQ <'.git/objects/pack/pack-'> (${ Id.VSub_Name pack))} spids: [286] ) ] redirects: [] ) (C {<git>} {<verify-pack>} {<-v>} {(${ Id.VSub_Name pack) <.pack>}) ] ) ] redirects: [] right: <Id.Lit_RBrace '}'> ) ) (command.ShFunction name: do_repack body: (BraceGroup left: <Id.Lit_LBrace '{'> children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'pack='> name:pack) op: assign_op.Equal rhs: { (command_sub left_token: <Id.Left_DollarParen '$('> child: (command.Pipeline children: [ (C {<printf>} { (DQ ($ Id.VSub_DollarName blob_1) <Id.Lit_BadBackslash '\\'> <n> ($ Id.VSub_DollarName blob_2) <Id.Lit_BadBackslash '\\'> <n> ($ Id.VSub_DollarName blob_3) <Id.Lit_BadBackslash '\\'> <n> ) } ) (C {<git>} {<pack-objects>} {($ Id.VSub_At '@')} {<'.git/objects/pack/pack'>} ) ] negated: F stderr_indices: [] ) right: <Id.Eof_RParen _> ) } spids: [318] ) ] redirects: [] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'pack='> name:pack) op: assign_op.Equal rhs: {(DQ <'.git/objects/pack/pack-'> (${ Id.VSub_Name pack))} spids: [349] ) ] redirects: [] ) ] ) ] redirects: [] right: <Id.Lit_RBrace '}'> ) ) (command.ShFunction name: do_corrupt_object body: (BraceGroup left: <Id.Lit_LBrace '{'> children: [ (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp] children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'ofs='> name:ofs) op: assign_op.Equal rhs: { (command_sub left_token: <Id.Left_DollarParen '$('> child: (command.Pipeline children: [ (command.Simple words: [{<git>} {<show-index>}] redirects: [ (redir op: <Id.Redir_Less '<'> loc: (redir_loc.Fd fd:0) arg: {(${ Id.VSub_Name pack) <.idx>} ) ] more_env: [] do_fork: T ) (C {<grep>} {($ Id.VSub_Number 1)}) (C {<cut>} {<-f1>} {<-d> (DQ <' '>)}) ] negated: F stderr_indices: [] ) right: <Id.Eof_RParen _> ) } spids: [367] ) ] redirects: [] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'ofs='> name:ofs) op: assign_op.Equal rhs: { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: {($ Id.VSub_DollarName ofs)} right: {($ Id.VSub_Number 2)} ) ) } spids: [401] ) ] redirects: [] ) (C {<chmod>} {<Id.Lit_Other '+'> <w>} {(${ Id.VSub_Name pack) <.pack>}) (C {<dd>} {<Id.Lit_VarLike 'of='> (${ Id.VSub_Name pack) <.pack>} {<Id.Lit_VarLike 'bs='> <1>} {<Id.Lit_VarLike 'conv='> <notrunc>} {<Id.Lit_VarLike 'seek='> ($ Id.VSub_DollarName ofs)} ) (C {<test_must_fail>} {<git>} {<verify-pack>} {(${ Id.VSub_Name pack) <.pack>}) ] ) ] redirects: [] right: <Id.Lit_RBrace '}'> ) ) (command.Simple words: [{<printf>} {(SQ <'\\0'>)}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<zero>})] more_env: [] do_fork: T ) (C {<test_expect_success>} {(SQ <'initial setup validation'>)} { (SQ <'create_test_files &&\n'> <' create_new_pack &&\n'> <' git prune-packed &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'create corruption in header of first object'>)} { (SQ <'do_corrupt_object $blob_1 0 < zero &&\n'> <' test_must_fail git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_1 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and loose copy of first delta allows for partial recovery'>)} { (SQ <'git prune-packed &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' test_must_fail git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'create corruption in data of first object'>)} { (SQ <'create_new_pack &&\n'> <' git prune-packed &&\n'> <' chmod +w ${pack}.pack &&\n'> <' perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&\n'> <' test_must_fail git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_1 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and loose copy of second object allows for partial recovery'>)} { (SQ <'git prune-packed &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' test_must_fail git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'create corruption in header of first delta'>)} { (SQ <'create_new_pack &&\n'> <' git prune-packed &&\n'> <' do_corrupt_object $blob_2 0 < zero &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and then a repack "clears" the corruption'>)} { (SQ <'do_repack &&\n'> <' git prune-packed &&\n'> <' git verify-pack ${pack}.pack &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'create corruption in data of first delta'>)} { (SQ <'create_new_pack &&\n'> <' git prune-packed &&\n'> <' chmod +w ${pack}.pack &&\n'> <' perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and then a repack "clears" the corruption'>)} { (SQ <'do_repack &&\n'> <' git prune-packed &&\n'> <' git verify-pack ${pack}.pack &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'corruption in delta base reference of first delta (OBJ_REF_DELTA)'>)} { (SQ <'create_new_pack &&\n'> <' git prune-packed &&\n'> <' do_corrupt_object $blob_2 2 < zero &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and then a repack "clears" the corruption'>)} { (SQ <'do_repack &&\n'> <' git prune-packed &&\n'> <' git verify-pack ${pack}.pack &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)'>)} { (SQ <'create_new_pack --delta-base-offset &&\n'> <' git prune-packed &&\n'> <' do_corrupt_object $blob_2 2 < zero &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and then a repack "clears" the corruption'>)} { (SQ <'do_repack --delta-base-offset &&\n'> <' git prune-packed &&\n'> <' git verify-pack ${pack}.pack &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)'>)} { (SQ <'create_new_pack --delta-base-offset &&\n'> <' git prune-packed &&\n'> <' printf "\\001" | do_corrupt_object $blob_2 2 &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and then a repack "clears" the corruption'>)} { (SQ <'do_repack --delta-base-offset &&\n'> <' git prune-packed &&\n'> <' git verify-pack ${pack}.pack &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and a redundant pack allows for full recovery too'>)} { (SQ <'do_corrupt_object $blob_2 2 < zero &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null &&\n'> <' mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_1 &&\n'> <' git hash-object -t blob -w file_2 &&\n'> <' printf "$blob_1\\n$blob_2\\n" | git pack-objects .git/objects/pack/pack &&\n'> <' git prune-packed &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'corruption of delta base reference pointing to wrong object'>)} { (SQ <'create_new_pack --delta-base-offset &&\n'> <' git prune-packed &&\n'> <' printf "\\220\\033" | do_corrupt_object $blob_3 2 &&\n'> <' git cat-file blob $blob_1 >/dev/null &&\n'> <' git cat-file blob $blob_2 >/dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 >/dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... but having a loose copy allows for full recovery'>)} { (SQ <'mv ${pack}.idx tmp &&\n'> <' git hash-object -t blob -w file_3 &&\n'> <' mv tmp ${pack}.idx &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'... and then a repack "clears" the corruption'>)} { (SQ <'do_repack --delta-base-offset --no-reuse-delta &&\n'> <' git prune-packed &&\n'> <' git verify-pack ${pack}.pack &&\n'> <' git cat-file blob $blob_1 > /dev/null &&\n'> <' git cat-file blob $blob_2 > /dev/null &&\n'> <' git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_expect_success>} {(SQ <'corrupting header to have too small output buffer fails unpack'>)} { (SQ <'create_new_pack &&\n'> <' git prune-packed &&\n'> <' printf "\\262\\001" | do_corrupt_object $blob_1 0 &&\n'> <' test_must_fail git cat-file blob $blob_1 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_2 > /dev/null &&\n'> <' test_must_fail git cat-file blob $blob_3 > /dev/null'> ) } ) (C {<test_done>}) ] )