2008-05-10 06:01:55 +02:00
|
|
|
#!/bin/sh
|
|
|
|
|
2008-09-03 10:59:33 +02:00
|
|
|
test_description='git repack works correctly'
|
2008-05-10 06:01:55 +02:00
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
2008-06-29 02:25:05 +02:00
|
|
|
fsha1=
|
|
|
|
csha1=
|
|
|
|
tsha1=
|
|
|
|
|
2008-11-13 21:11:46 +01:00
|
|
|
test_expect_success '-A with -d option leaves unreachable objects unpacked' '
|
2008-05-10 06:01:55 +02:00
|
|
|
echo content > file1 &&
|
|
|
|
git add . &&
|
2010-04-15 00:09:57 +02:00
|
|
|
test_tick &&
|
2008-05-10 06:01:55 +02:00
|
|
|
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) &&
|
2010-04-15 00:09:57 +02:00
|
|
|
test_tick &&
|
2008-05-10 06:01:55 +02:00
|
|
|
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 &&
|
2010-04-15 00:09:57 +02:00
|
|
|
test_tick &&
|
2008-05-10 06:01:55 +02:00
|
|
|
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 |
|
2008-09-30 10:03:55 +02:00
|
|
|
egrep "^($fsha1|$csha1|$tsha1) " |
|
2008-05-10 06:01:55 +02:00
|
|
|
sort | uniq | wc -l) &&
|
|
|
|
git show $fsha1 &&
|
|
|
|
git show $csha1 &&
|
|
|
|
git show $tsha1 &&
|
2010-04-15 00:09:57 +02:00
|
|
|
# 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 &&
|
2008-05-10 06:01:55 +02:00
|
|
|
# and repack
|
|
|
|
git repack -A -d -l &&
|
|
|
|
# verify objects are retained unpacked
|
|
|
|
test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
|
2008-09-30 10:03:55 +02:00
|
|
|
egrep "^($fsha1|$csha1|$tsha1) " |
|
2008-05-10 06:01:55 +02:00
|
|
|
sort | uniq | wc -l) &&
|
|
|
|
git show $fsha1 &&
|
|
|
|
git show $csha1 &&
|
|
|
|
git show $tsha1
|
|
|
|
'
|
|
|
|
|
2008-06-29 02:25:05 +02:00
|
|
|
compare_mtimes ()
|
|
|
|
{
|
2009-01-28 10:52:26 +01:00
|
|
|
read tref rest &&
|
|
|
|
while read t rest; do
|
2015-03-25 06:29:10 +01:00
|
|
|
test "$tref" = "$t" || return 1
|
2009-01-28 10:52:26 +01:00
|
|
|
done
|
2008-06-29 02:25:05 +02:00
|
|
|
}
|
|
|
|
|
2008-11-13 21:11:46 +01:00
|
|
|
test_expect_success '-A without -d option leaves unreachable objects packed' '
|
2008-06-29 02:25:05 +02:00
|
|
|
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 &&
|
2010-04-15 00:09:57 +02:00
|
|
|
test_tick &&
|
2008-06-29 02:25:05 +02:00
|
|
|
git repack -A -l &&
|
2008-11-13 21:11:46 +01:00
|
|
|
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 &&
|
2009-01-28 10:52:26 +01:00
|
|
|
test-chmtime -v +0 "$tmppack" "$fsha1path" "$csha1path" "$tsha1path" \
|
|
|
|
> mtimes &&
|
|
|
|
compare_mtimes < mtimes
|
2008-06-29 02:25:05 +02:00
|
|
|
'
|
|
|
|
|
2012-04-07 12:30:09 +02:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2014-10-17 02:44:49 +02:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
repack: add --keep-unreachable option
The usual way to do a full repack (and what is done by
git-gc) is to run "repack -Ad --unpack-unreachable=<when>",
which will loosen any unreachable objects newer than
"<when>", and drop any older ones.
This is a safer alternative to "repack -ad", because
"<when>" becomes a grace period during which we will not
drop any new objects that are about to be referenced.
However, it isn't perfectly safe. It's always possible that
a process is about to reference an old object. Even if that
process were to take care to update the timestamp on the
object, there is no atomicity with a simultaneously running
"repack" process.
So while unlikely, there is a small race wherein we may drop
an object that is in the process of being referenced. If you
do automated repacking on a large number of active
repositories, you may hit it eventually, and the result is a
corrupted repository.
It would be nice to fix that race in the long run, but it's
complicated. In the meantime, there is a much simpler
strategy for automated repository maintenance: do not drop
objects at all. We already have a "--keep-unreachable"
option in pack-objects; we just need to plumb it through
from git-repack.
Note that this _isn't_ plumbed through from git-gc, so at
this point it's strictly a tool for people doing their own
advanced repository maintenance strategy.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-13 06:36:28 +02:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
repack: extend --keep-unreachable to loose objects
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>
2016-06-13 06:38:04 +02:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2008-05-10 06:01:55 +02:00
|
|
|
test_done
|