#!/bin/sh global test_description := ''git repack works correctly'' source ./test-lib.sh global fsha1 := '' global csha1 := '' global tsha1 := '' test_expect_success '-A with -d option leaves unreachable objects unpacked' ' echo content > file1 && git add . && test_tick && git commit -m initial_commit && # create a transient branch with unique content git checkout -b transient_branch && echo more content >> file1 && # record the objects created in the database for file, commit, tree fsha1=$(git hash-object file1) && test_tick && git commit -a -m more_content && csha1=$(git rev-parse HEAD^{commit}) && tsha1=$(git rev-parse HEAD^{tree}) && git checkout master && echo even more content >> file1 && test_tick && git commit -a -m even_more_content && # delete the transient branch git branch -D transient_branch && # pack the repo git repack -A -d -l && # verify objects are packed in repository test 3 = $(git verify-pack -v -- .git/objects/pack/*.idx | egrep "^($fsha1|$csha1|$tsha1) " | sort | uniq | wc -l) && git show $fsha1 && git show $csha1 && git show $tsha1 && # now expire the reflog, while keeping reachable ones but expiring # unreachables immediately test_tick && sometimeago=$(( $test_tick - 10000 )) && git reflog expire --expire=$sometimeago --expire-unreachable=$test_tick --all && # and repack git repack -A -d -l && # verify objects are retained unpacked test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx | egrep "^($fsha1|$csha1|$tsha1) " | sort | uniq | wc -l) && git show $fsha1 && git show $csha1 && git show $tsha1 ' proc compare_mtimes { read tref rest && while read t rest { test $tref = $t || return 1 } } test_expect_success '-A without -d option leaves unreachable objects packed' ' fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") && fsha1path=".git/objects/$fsha1path" && csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") && csha1path=".git/objects/$csha1path" && tsha1path=$(echo "$tsha1" | sed -e "s|\(..\)|\1/|") && tsha1path=".git/objects/$tsha1path" && git branch transient_branch $csha1 && git repack -a -d -l && test ! -f "$fsha1path" && test ! -f "$csha1path" && test ! -f "$tsha1path" && test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) && packfile=$(ls .git/objects/pack/pack-*.pack) && git branch -D transient_branch && test_tick && git repack -A -l && test ! -f "$fsha1path" && test ! -f "$csha1path" && test ! -f "$tsha1path" && git show $fsha1 && git show $csha1 && git show $tsha1 ' test_expect_success 'unpacked objects receive timestamp of pack file' ' tmppack=".git/objects/pack/tmp_pack" && ln "$packfile" "$tmppack" && git repack -A -l -d && test-chmtime -v +0 "$tmppack" "$fsha1path" "$csha1path" "$tsha1path" \ > mtimes && compare_mtimes < mtimes ' test_expect_success 'do not bother loosening old objects' ' obj1=$(echo one | git hash-object -w --stdin) && obj2=$(echo two | git hash-object -w --stdin) && pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) && pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) && git prune-packed && git cat-file -p $obj1 && git cat-file -p $obj2 && test-chmtime =-86400 .git/objects/pack/pack-$pack2.pack && git repack -A -d --unpack-unreachable=1.hour.ago && git cat-file -p $obj1 && test_must_fail git cat-file -p $obj2 ' test_expect_success 'keep packed objects found only in index' ' echo my-unique-content >file && git add file && git commit -m "make it reachable" && git gc && git reset HEAD^ && git reflog expire --expire=now --all && git add file && test-chmtime =-86400 .git/objects/pack/* && git gc --prune=1.hour.ago && git cat-file blob :file ' test_expect_success 'repack -k keeps unreachable packed objects' ' # create packed-but-unreachable object sha1=$(echo unreachable-packed | git hash-object -w --stdin) && pack=$(echo $sha1 | git pack-objects .git/objects/pack/pack) && git prune-packed && # -k should keep it git repack -adk && git cat-file -p $sha1 && # and double check that without -k it would have been removed git repack -ad && test_must_fail git cat-file -p $sha1 ' test_expect_success 'repack -k packs unreachable loose objects' ' # create loose unreachable object sha1=$(echo would-be-deleted-loose | git hash-object -w --stdin) && objpath=.git/objects/$(echo $sha1 | sed "s,..,&/,") && test_path_is_file $objpath && # and confirm that the loose object goes away, but we can # still access it (ergo, it is packed) git repack -adk && test_path_is_missing $objpath && git cat-file -p $sha1 ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"git repack works correctly">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:fsha1) op:Equal rhs:{(SQ )} spids:[15])] spids: [15] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:csha1) op:Equal rhs:{(SQ )} spids:[17])] spids: [17] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:tsha1) op:Equal rhs:{(SQ )} spids:[19])] spids: [19] ) (C {(test_expect_success)} {(SQ <"-A with -d option leaves unreachable objects unpacked">)} { (SQ <"\n"> <"\techo content > file1 &&\n"> <"\tgit add . &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m initial_commit &&\n"> <"\t# create a transient branch with unique content\n"> <"\tgit checkout -b transient_branch &&\n"> <"\techo more content >> file1 &&\n"> <"\t# record the objects created in the database for file, commit, tree\n"> <"\tfsha1=$(git hash-object file1) &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -a -m more_content &&\n"> <"\tcsha1=$(git rev-parse HEAD^{commit}) &&\n"> <"\ttsha1=$(git rev-parse HEAD^{tree}) &&\n"> <"\tgit checkout master &&\n"> <"\techo even more content >> file1 &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -a -m even_more_content &&\n"> <"\t# delete the transient branch\n"> <"\tgit branch -D transient_branch &&\n"> <"\t# pack the repo\n"> <"\tgit repack -A -d -l &&\n"> <"\t# verify objects are packed in repository\n"> <"\ttest 3 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n"> <"\t\t egrep \"^($fsha1|$csha1|$tsha1) \" |\n"> <"\t\t sort | uniq | wc -l) &&\n"> <"\tgit show $fsha1 &&\n"> <"\tgit show $csha1 &&\n"> <"\tgit show $tsha1 &&\n"> <"\t# now expire the reflog, while keeping reachable ones but expiring\n"> <"\t# unreachables immediately\n"> <"\ttest_tick &&\n"> <"\tsometimeago=$(( $test_tick - 10000 )) &&\n"> <"\tgit reflog expire --expire=$sometimeago --expire-unreachable=$test_tick --all &&\n"> <"\t# and repack\n"> <"\tgit repack -A -d -l &&\n"> <"\t# verify objects are retained unpacked\n"> <"\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n"> <"\t\t egrep \"^($fsha1|$csha1|$tsha1) \" |\n"> <"\t\t sort | uniq | wc -l) &&\n"> <"\tgit show $fsha1 &&\n"> <"\tgit show $csha1 &&\n"> <"\tgit show $tsha1\n"> ) } ) (FuncDef name: compare_mtimes body: (BraceGroup children: [ (AndOr children: [ (C {(read)} {(tref)} {(rest)}) (While cond: [(Sentence child:(C {(read)} {(t)} {(rest)}) terminator:)] body: (DoGroup children: [ (AndOr children: [ (C {(test)} {(DQ ($ VSub_Name "$tref"))} {(Lit_Other "=")} {(DQ ($ VSub_Name "$t"))} ) (ControlFlow token: arg_word: {(1)} ) ] op_id: Op_DPipe ) ] spids: [101 123] ) ) ] op_id: Op_DAmp ) ] spids: [80] ) spids: [75 79] ) (C {(test_expect_success)} {(SQ <"-A without -d option leaves unreachable objects packed">)} { (SQ <"\n"> <"\tfsha1path=$(echo \"$fsha1\" | sed -e \"s|\\(..\\)|\\1/|\") &&\n"> <"\tfsha1path=\".git/objects/$fsha1path\" &&\n"> <"\tcsha1path=$(echo \"$csha1\" | sed -e \"s|\\(..\\)|\\1/|\") &&\n"> <"\tcsha1path=\".git/objects/$csha1path\" &&\n"> <"\ttsha1path=$(echo \"$tsha1\" | sed -e \"s|\\(..\\)|\\1/|\") &&\n"> <"\ttsha1path=\".git/objects/$tsha1path\" &&\n"> <"\tgit branch transient_branch $csha1 &&\n"> <"\tgit repack -a -d -l &&\n"> <"\ttest ! -f \"$fsha1path\" &&\n"> <"\ttest ! -f \"$csha1path\" &&\n"> <"\ttest ! -f \"$tsha1path\" &&\n"> <"\ttest 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) &&\n"> <"\tpackfile=$(ls .git/objects/pack/pack-*.pack) &&\n"> <"\tgit branch -D transient_branch &&\n"> <"\ttest_tick &&\n"> <"\tgit repack -A -l &&\n"> <"\ttest ! -f \"$fsha1path\" &&\n"> <"\ttest ! -f \"$csha1path\" &&\n"> <"\ttest ! -f \"$tsha1path\" &&\n"> <"\tgit show $fsha1 &&\n"> <"\tgit show $csha1 &&\n"> <"\tgit show $tsha1\n"> ) } ) (C {(test_expect_success)} {(SQ <"unpacked objects receive timestamp of pack file">)} { (SQ <"\n"> <"\ttmppack=\".git/objects/pack/tmp_pack\" &&\n"> <"\tln \"$packfile\" \"$tmppack\" &&\n"> <"\tgit repack -A -l -d &&\n"> <"\ttest-chmtime -v +0 \"$tmppack\" \"$fsha1path\" \"$csha1path\" \"$tsha1path\" \\\n"> <"\t\t> mtimes &&\n"> <"\tcompare_mtimes < mtimes\n"> ) } ) (C {(test_expect_success)} {(SQ <"do not bother loosening old objects">)} { (SQ <"\n"> <"\tobj1=$(echo one | git hash-object -w --stdin) &&\n"> <"\tobj2=$(echo two | git hash-object -w --stdin) &&\n"> <"\tpack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) &&\n"> <"\tpack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) &&\n"> <"\tgit prune-packed &&\n"> <"\tgit cat-file -p $obj1 &&\n"> <"\tgit cat-file -p $obj2 &&\n"> <"\ttest-chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&\n"> <"\tgit repack -A -d --unpack-unreachable=1.hour.ago &&\n"> <"\tgit cat-file -p $obj1 &&\n"> <"\ttest_must_fail git cat-file -p $obj2\n"> ) } ) (C {(test_expect_success)} {(SQ <"keep packed objects found only in index">)} { (SQ <"\n"> <"\techo my-unique-content >file &&\n"> <"\tgit add file &&\n"> <"\tgit commit -m \"make it reachable\" &&\n"> <"\tgit gc &&\n"> <"\tgit reset HEAD^ &&\n"> <"\tgit reflog expire --expire=now --all &&\n"> <"\tgit add file &&\n"> <"\ttest-chmtime =-86400 .git/objects/pack/* &&\n"> <"\tgit gc --prune=1.hour.ago &&\n"> <"\tgit cat-file blob :file\n"> ) } ) (C {(test_expect_success)} {(SQ <"repack -k keeps unreachable packed objects">)} { (SQ <"\n"> <"\t# create packed-but-unreachable object\n"> <"\tsha1=$(echo unreachable-packed | git hash-object -w --stdin) &&\n"> <"\tpack=$(echo $sha1 | git pack-objects .git/objects/pack/pack) &&\n"> <"\tgit prune-packed &&\n"> <"\n"> <"\t# -k should keep it\n"> <"\tgit repack -adk &&\n"> <"\tgit cat-file -p $sha1 &&\n"> <"\n"> <"\t# and double check that without -k it would have been removed\n"> <"\tgit repack -ad &&\n"> <"\ttest_must_fail git cat-file -p $sha1\n"> ) } ) (C {(test_expect_success)} {(SQ <"repack -k packs unreachable loose objects">)} { (SQ <"\n"> <"\t# create loose unreachable object\n"> <"\tsha1=$(echo would-be-deleted-loose | git hash-object -w --stdin) &&\n"> <"\tobjpath=.git/objects/$(echo $sha1 | sed \"s,..,&/,\") &&\n"> <"\ttest_path_is_file $objpath &&\n"> <"\n"> <"\t# and confirm that the loose object goes away, but we can\n"> <"\t# still access it (ergo, it is packed)\n"> <"\tgit repack -adk &&\n"> <"\ttest_path_is_missing $objpath &&\n"> <"\tgit cat-file -p $sha1\n"> ) } ) (C {(test_done)}) ] )