mirror of
https://github.com/git/git.git
synced 2024-12-20 07:13:52 +08:00
e26a8c4721
If you use "repack -adk" currently, we will pack all objects that are already packed into the new pack, and then drop the old packs. However, loose unreachable objects will be left as-is. In theory these are meant to expire eventually with "git prune". But if you are using "repack -k", you probably want to keep things forever and therefore do not run "git prune" at all. Meaning those loose objects may build up over time and end up fooling any object-count heuristics (such as the one done by "gc --auto", though since git-gc does not support "repack -k", this really applies to whatever custom scripts people might have driving "repack -k"). With this patch, we instead stuff any loose unreachable objects into the pack along with the already-packed unreachable objects. This may seem wasteful, but it is really no more so than using "repack -k" in the first place. We are at a slight disadvantage, in that we have no useful ordering for the result, or names to hand to the delta code. However, this is again no worse than what "repack -k" is already doing for the packed objects. The packing of these objects doesn't matter much because they should not be accessed frequently (unless they actually _do_ become referenced, but then they would get moved to a different part of the packfile during the next repack). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
154 lines
4.5 KiB
Bash
Executable File
154 lines
4.5 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='git repack works correctly'
|
|
|
|
. ./test-lib.sh
|
|
|
|
fsha1=
|
|
csha1=
|
|
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
|
|
'
|
|
|
|
compare_mtimes ()
|
|
{
|
|
read tref rest &&
|
|
while read t rest; do
|
|
test "$tref" = "$t" || return 1
|
|
done
|
|
}
|
|
|
|
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
|