repack: modify behavior of -A option to leave unreferenced objects unpacked
authorBrandon Casey <drafnel@gmail.com>
Sat, 10 May 2008 04:01:55 +0000 (23:01 -0500)
committerJunio C Hamano <gitster@pobox.com>
Sun, 11 May 2008 18:24:48 +0000 (11:24 -0700)
The previous behavior of the -A option was to retain any previously
packed objects which had become unreferenced, and place them into the newly
created pack file.  Since git-gc, when run automatically with the --auto
option, calls repack with the -A option, this had the effect of retaining
unreferenced packed objects indefinitely. To avoid this scenario, the
user was required to run git-gc with the little known --prune option or
to manually run repack with the -a option.

This patch changes the behavior of the -A option so that unreferenced
objects that exist in any pack file being replaced, will be unpacked into
the repository. The unreferenced loose objects can then be garbage collected
by git-gc (i.e. git-prune) based on the gc.pruneExpire setting.

Also add new tests for checking whether unreferenced objects which were
previously packed are properly left in the repository unpacked after
repacking.

Signed-off-by: Brandon Casey <drafnel@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-repack.sh
t/t7701-repack-unpack-unreachable.sh [new file with mode: 0755]

index e18eb3f5dcf42abfbd125594877ececf92c3d9b6..a0e06ed0768f65241b59cfdec7b0f6b833580c53 100755 (executable)
@@ -30,7 +30,7 @@ do
        -n)     no_update_info=t ;;
        -a)     all_into_one=t ;;
        -A)     all_into_one=t
-               keep_unreachable=--keep-unreachable ;;
+               keep_unreachable=t ;;
        -d)     remove_redundant=t ;;
        -q)     quiet=-q ;;
        -f)     no_reuse=--no-reuse-object ;;
@@ -78,9 +78,6 @@ case ",$all_into_one," in
        if test -z "$args"
        then
                args='--unpacked --incremental'
-       elif test -n "$keep_unreachable"
-       then
-               args="$args $keep_unreachable"
        fi
        ;;
 esac
@@ -130,7 +127,18 @@ then
                  do
                        case " $fullbases " in
                        *" $e "*) ;;
-                       *)      rm -f "$e.pack" "$e.idx" "$e.keep" ;;
+                       *)
+                               rm -f "$e.idx" "$e.keep"
+                               if test -n "$keep_unreachable" &&
+                                  test -f "$e.pack"
+                               then
+                                       git unpack-objects < "$e.pack" || {
+                                               echo >&2 "Failed unpacking unreachable objects from redundant pack file $e.pack"
+                                               exit 1
+                                       }
+                               fi
+                               rm -f "$e.pack"
+                       ;;
                        esac
                  done
                )
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
new file mode 100755 (executable)
index 0000000..6a5211f
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+test_description='git-repack works correctly'
+
+. ./test-lib.sh
+
+test_expect_success '-A option leaves unreachable objects unpacked' '
+       echo content > file1 &&
+       git add . &&
+       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) &&
+       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 &&
+       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 |
+                  grep -e "^$fsha1 " -e "^$csha1 " -e "^$tsha1 " |
+                  sort | uniq | wc -l) &&
+       git show $fsha1 &&
+       git show $csha1 &&
+       git show $tsha1 &&
+       # now expire the reflog
+       sleep 1 &&
+       git reflog expire --expire-unreachable=now --all &&
+       # and repack
+       git repack -A -d -l &&
+       # verify objects are retained unpacked
+       test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+                  grep -e "^$fsha1 " -e "^$csha1 " -e "^$tsha1 " |
+                  sort | uniq | wc -l) &&
+       git show $fsha1 &&
+       git show $csha1 &&
+       git show $tsha1
+'
+
+test_done