(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:test_description) op: assign_op.Equal rhs: {(SQ <'resilience to pack corruptions with redundant objects'>)} spids: [13] ) ] ) (C {<.>} {<'./test-lib.sh'>}) (command.ShFunction name: create_test_files body: (BraceGroup 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>})] 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>})] 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>})] do_fork: T ) (command.Simple words: [{<echo>} {(DQ <' base '>)}] redirects: [(redir op:<Id.Redir_DGreat '>>'> loc:(redir_loc.Fd fd:1) arg:{<file_1>})] do_fork: T ) (command.Simple words: [{<echo>} {(DQ <' delta1 '>)}] redirects: [(redir op:<Id.Redir_DGreat '>>'> loc:(redir_loc.Fd fd:1) arg:{<file_2>})] 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>})] 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>})] 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>})] do_fork: T ) ] ) ] ) ) (command.ShFunction name: create_new_pack body: (BraceGroup 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 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>}) ) } spids: [201] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name 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>}) ) } spids: [219] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name 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>}) ) } spids: [237] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name 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 ) ) } spids: [255] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:pack) op: assign_op.Equal rhs: {(DQ <'.git/objects/pack/pack-'> (${ Id.VSub_Name pack))} spids: [286] ) ] ) (C {<git>} {<verify-pack>} {<-v>} {(${ Id.VSub_Name pack) <.pack>}) ] ) ] ) ) (command.ShFunction name: do_repack body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name 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 ) ) } spids: [318] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:pack) op: assign_op.Equal rhs: {(DQ <'.git/objects/pack/pack-'> (${ Id.VSub_Name pack))} spids: [349] ) ] ) ] ) ] ) ) (command.ShFunction name: do_corrupt_object body: (BraceGroup 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 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>} ) ] do_fork: T ) (C {<grep>} {($ Id.VSub_Number '$1')}) (C {<cut>} {<-f1>} {<-d> (DQ <' '>)}) ] negated: F ) ) } spids: [367] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name 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] ) ] ) (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>}) ] ) ] ) ) (command.Simple words: [{<printf>} {(SQ <'\\0'>)}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<zero>})] 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>}) ] )