Merge branch 'jk/prune-mtime'

Tighten the logic to decide that an unreachable cruft is
sufficiently old by covering corner cases such as an ancient object
becoming reachable and then going unreachable again, in which case
its retention period should be prolonged.

* jk/prune-mtime: (28 commits)
  drop add_object_array_with_mode
  revision: remove definition of unused 'add_object' function
  pack-objects: double-check options before discarding objects
  repack: pack objects mentioned by the index
  pack-objects: use argv_array
  reachable: use revision machinery's --indexed-objects code
  rev-list: add --indexed-objects option
  rev-list: document --reflog option
  t5516: test pushing a tag of an otherwise unreferenced blob
  traverse_commit_list: support pending blobs/trees with paths
  make add_object_array_with_context interface more sane
  write_sha1_file: freshen existing objects
  pack-objects: match prune logic for discarding objects
  pack-objects: refactor unpack-unreachable expiration check
  prune: keep objects reachable from recent objects
  sha1_file: add for_each iterators for loose and packed objects
  count-objects: use for_each_loose_file_in_objdir
  count-objects: do not use xsize_t when counting object size
  prune-packed: use for_each_loose_file_in_objdir
  reachable: mark index blobs as SEEN
  ...
This commit is contained in:
Junio C Hamano
2014-10-29 10:07:56 -07:00
23 changed files with 849 additions and 449 deletions

View File

@ -1277,4 +1277,17 @@ EOF
git push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/master:refs/heads/foo
'
test_expect_success 'pushing a tag pushes the tagged object' '
rm -rf dst.git &&
blob=$(echo unreferenced | git hash-object -w --stdin) &&
git tag -m foo tag-of-blob $blob &&
git init --bare dst.git &&
git push dst.git tag-of-blob &&
# the receiving index-pack should have noticed
# any problems, but we double check
echo unreferenced >expect &&
git --git-dir=dst.git cat-file blob tag-of-blob >actual &&
test_cmp expect actual
'
test_done

View File

@ -73,4 +73,27 @@ test_expect_success 'symleft flag bit is propagated down from tag' '
test_cmp expect actual
'
test_expect_success 'rev-list can show index objects' '
# Of the blobs and trees in the index, note:
#
# - we do not show two/three, because it is the
# same blob as "one", and we show objects only once
#
# - we do show the tree "two", because it has a valid cache tree
# from the last commit
#
# - we do not show the root tree; since we updated the index, it
# does not have a valid cache tree
#
cat >expect <<-\EOF
8e4020bb5a8d8c873b25de15933e75cc0fc275df one
d9d3a7417b9605cfd88ee6306b28dadc29e6ab08 only-in-index
9200b628cf9dc883a85a7abc8d6e6730baee589c two
EOF
echo only-in-index >only-in-index &&
git add only-in-index &&
git rev-list --objects --indexed-objects >actual &&
test_cmp expect actual
'
test_done

132
t/t6501-freshen-objects.sh Executable file
View File

@ -0,0 +1,132 @@
#!/bin/sh
#
# This test covers the handling of objects which might have old
# mtimes in the filesystem (because they were used previously)
# and are just now becoming referenced again.
#
# We're going to do two things that are a little bit "fake" to
# help make our simulation easier:
#
# 1. We'll turn off reflogs. You can still run into
# problems with reflogs on, but your objects
# don't get pruned until both the reflog expiration
# has passed on their references, _and_ they are out
# of prune's expiration period. Dropping reflogs
# means we only have to deal with one variable in our tests,
# but the results generalize.
#
# 2. We'll use a temporary index file to create our
# works-in-progress. Most workflows would mention
# referenced objects in the index, which prune takes
# into account. However, many operations don't. For
# example, a partial commit with "git commit foo"
# will use a temporary index. Or they may not need
# an index at all (e.g., creating a new commit
# to refer to an existing tree).
test_description='check pruning of dependent objects'
. ./test-lib.sh
# We care about reachability, so we do not want to use
# the normal test_commit, which creates extra tags.
add () {
echo "$1" >"$1" &&
git add "$1"
}
commit () {
test_tick &&
add "$1" &&
git commit -m "$1"
}
maybe_repack () {
if test -n "$repack"; then
git repack -ad
fi
}
for repack in '' true; do
title=${repack:+repack}
title=${title:-loose}
test_expect_success "make repo completely empty ($title)" '
rm -rf .git &&
git init
'
test_expect_success "disable reflogs ($title)" '
git config core.logallrefupdates false &&
rm -rf .git/logs
'
test_expect_success "setup basic history ($title)" '
commit base
'
test_expect_success "create and abandon some objects ($title)" '
git checkout -b experiment &&
commit abandon &&
maybe_repack &&
git checkout master &&
git branch -D experiment
'
test_expect_success "simulate time passing ($title)" '
find .git/objects -type f |
xargs test-chmtime -v -86400
'
test_expect_success "start writing new commit with old blob ($title)" '
tree=$(
GIT_INDEX_FILE=index.tmp &&
export GIT_INDEX_FILE &&
git read-tree HEAD &&
add unrelated &&
add abandon &&
git write-tree
)
'
test_expect_success "simultaneous gc ($title)" '
git gc --prune=12.hours.ago
'
test_expect_success "finish writing out commit ($title)" '
commit=$(echo foo | git commit-tree -p HEAD $tree) &&
git update-ref HEAD $commit
'
# "abandon" blob should have been rescued by reference from new tree
test_expect_success "repository passes fsck ($title)" '
git fsck
'
test_expect_success "abandon objects again ($title)" '
git reset --hard HEAD^ &&
find .git/objects -type f |
xargs test-chmtime -v -86400
'
test_expect_success "start writing new commit with same tree ($title)" '
tree=$(
GIT_INDEX_FILE=index.tmp &&
export GIT_INDEX_FILE &&
git read-tree HEAD &&
add abandon &&
add unrelated &&
git write-tree
)
'
test_expect_success "simultaneous gc ($title)" '
git gc --prune=12.hours.ago
'
# tree should have been refreshed by write-tree
test_expect_success "finish writing out commit ($title)" '
commit=$(echo foo | git commit-tree -p HEAD $tree) &&
git update-ref HEAD $commit
'
done
test_done

View File

@ -109,4 +109,17 @@ test_expect_success 'do not bother loosening old objects' '
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_done