Merge branch 'jc/maint-1.6.0-keep-pack'
authorJunio C Hamano <gitster@pobox.com>
Thu, 2 Apr 2009 05:34:19 +0000 (22:34 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Apr 2009 05:34:19 +0000 (22:34 -0700)
* jc/maint-1.6.0-keep-pack:
pack-objects: don't loosen objects available in alternate or kept packs
t7700: demonstrate repack flaw which may loosen objects unnecessarily
Remove --kept-pack-only option and associated infrastructure
pack-objects: only repack or loosen objects residing in "local" packs
git-repack.sh: don't use --kept-pack-only option to pack-objects
t7700-repack: add two new tests demonstrating repacking flaws

Conflicts:
t/t7700-repack.sh

builtin-pack-objects.c
cache.h
git-repack.sh
revision.c
revision.h
sha1_file.c
t/t7700-repack.sh
index 2000d97ec406a439db81542684f77ebbec9d0172..9fc3b355470466bd5663e1fca1fe759e18869ee2 100644 (file)
@@ -1966,7 +1966,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
                const unsigned char *sha1;
                struct object *o;
 
-               if (p->pack_keep)
+               if (!p->pack_local || p->pack_keep)
                        continue;
                if (open_pack_index(p))
                        die("cannot open pack index");
@@ -1995,6 +1995,29 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
        free(in_pack.array);
 }
 
+static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
+{
+       static struct packed_git *last_found = (void *)1;
+       struct packed_git *p;
+
+       p = (last_found != (void *)1) ? last_found : packed_git;
+
+       while (p) {
+               if ((!p->pack_local || p->pack_keep) &&
+                       find_pack_entry_one(sha1, p)) {
+                       last_found = p;
+                       return 1;
+               }
+               if (p == last_found)
+                       p = packed_git;
+               else
+                       p = p->next;
+               if (p == last_found)
+                       p = p->next;
+       }
+       return 0;
+}
+
 static void loosen_unused_packed_objects(struct rev_info *revs)
 {
        struct packed_git *p;
@@ -2002,7 +2025,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
        const unsigned char *sha1;
 
        for (p = packed_git; p; p = p->next) {
-               if (p->pack_keep)
+               if (!p->pack_local || p->pack_keep)
                        continue;
 
                if (open_pack_index(p))
@@ -2010,7 +2033,8 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
 
                for (i = 0; i < p->num_objects; i++) {
                        sha1 = nth_packed_object_sha1(p, i);
-                       if (!locate_object_entry(sha1))
+                       if (!locate_object_entry(sha1) &&
+                               !has_sha1_pack_kept_or_nonlocal(sha1))
                                if (force_object_loose(sha1, p->mtime))
                                        die("unable to force loose object");
                }
@@ -2200,7 +2224,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                        continue;
                }
                if (!strcmp("--unpacked", arg) ||
-                   !strcmp("--kept-pack-only", arg) ||
                    !strcmp("--reflog", arg) ||
                    !strcmp("--all", arg)) {
                        use_internal_rev_list = 1;
diff --git a/cache.h b/cache.h
index f48e80bc057fb5970200cd12a791af56fa4eef8a..9cf5a13c2cbec321aa728f5024a48e3291fb697d 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -655,7 +655,6 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l
 extern int move_temp_to_file(const char *tmpfile, const char *filename);
 
 extern int has_sha1_pack(const unsigned char *sha1);
-extern int has_sha1_kept_pack(const unsigned char *sha1);
 extern int has_sha1_file(const unsigned char *sha1);
 extern int has_loose_object_nonlocal(const unsigned char *sha1);
 
index 0144c2d7b95d5393b7993c95e6aff46f18f01e8b..1782a23b26106545dde94a63a42340b3427cb04b 100755 (executable)
@@ -71,11 +71,7 @@ case ",$all_into_one," in
                                existing="$existing $e"
                        fi
                done
-               if test -n "$existing"
-               then
-                       args="--kept-pack-only"
-               fi
-               if test -n "$args" -a -n "$unpack_unreachable" -a \
+               if test -n "$existing" -a -n "$unpack_unreachable" -a \
                        -n "$remove_redundant"
                then
                        args="$args $unpack_unreachable"
index f5771c7898a939e34effb8c757c5a237830075b9..b6215cc72c77baa3f72d652e8457d3ace6e5f439 100644 (file)
@@ -1106,10 +1106,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->edge_hint = 1;
        } else if (!strcmp(arg, "--unpacked")) {
                revs->unpacked = 1;
-               revs->kept_pack_only = 0;
-       } else if (!strcmp(arg, "--kept-pack-only")) {
-               revs->unpacked = 1;
-               revs->kept_pack_only = 1;
        } else if (!prefixcmp(arg, "--unpacked=")) {
                die("--unpacked=<packfile> no longer supported.");
        } else if (!strcmp(arg, "-r")) {
@@ -1679,10 +1675,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
 {
        if (commit->object.flags & SHOWN)
                return commit_ignore;
-       if (revs->unpacked &&
-           (revs->kept_pack_only
-            ? has_sha1_kept_pack(commit->object.sha1)
-            : has_sha1_pack(commit->object.sha1)))
+       if (revs->unpacked && has_sha1_pack(commit->object.sha1))
                return commit_ignore;
        if (revs->show_all)
                return commit_show;
index ad123d78c582e11e27748a613fae5b17bd87b0e9..6e98b71b49a4db01761d45aa244424f2512c5a41 100644 (file)
@@ -50,7 +50,6 @@ struct rev_info {
                        edge_hint:1,
                        limited:1,
                        unpacked:1,
-                       kept_pack_only:1,
                        boundary:2,
                        left_right:1,
                        rewrite_parents:1,
index 54972f97e004e2794416baac2f79806a608dc88e..37e833b77d1ee556d18256154073a706ab11b3a4 100644 (file)
@@ -1919,8 +1919,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
        return 0;
 }
 
-static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
-                        int kept_pack_only)
+static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
 {
        static struct packed_git *last_found = (void *)1;
        struct packed_git *p;
@@ -1932,8 +1931,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
        p = (last_found == (void *)1) ? packed_git : last_found;
 
        do {
-               if (kept_pack_only && !p->pack_keep)
-                       goto next;
                if (p->num_bad_objects) {
                        unsigned i;
                        for (i = 0; i < p->num_bad_objects; i++)
@@ -1973,16 +1970,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
        return 0;
 }
 
-static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
-{
-       return find_pack_ent(sha1, e, 0);
-}
-
-static int find_kept_pack_entry(const unsigned char *sha1, struct pack_entry *e)
-{
-       return find_pack_ent(sha1, e, 1);
-}
-
 struct packed_git *find_sha1_pack(const unsigned char *sha1,
                                  struct packed_git *packs)
 {
@@ -2456,12 +2443,6 @@ int has_sha1_pack(const unsigned char *sha1)
        return find_pack_entry(sha1, &e);
 }
 
-int has_sha1_kept_pack(const unsigned char *sha1)
-{
-       struct pack_entry e;
-       return find_kept_pack_entry(sha1, &e);
-}
-
 int has_sha1_file(const unsigned char *sha1)
 {
        struct pack_entry e;
index f5682d66db2832311774fb68b7264002dfeb091f..6b29bff782f5a46bb6970d70598fd3be82c679fa 100755 (executable)
@@ -88,5 +88,66 @@ test_expect_failure 'packed obs in alt ODB are repacked when local repo has pack
        done
 '
 
+test_expect_success 'packed obs in alternate ODB kept pack are repacked' '
+       # swap the .keep so the commit object is in the pack with .keep
+       for p in alt_objects/pack/*.pack
+       do
+               base_name=$(basename $p .pack)
+               if test -f alt_objects/pack/$base_name.keep
+               then
+                       rm alt_objects/pack/$base_name.keep
+               else
+                       touch alt_objects/pack/$base_name.keep
+               fi
+       done
+       git repack -a -d &&
+       myidx=$(ls -1 .git/objects/pack/*.idx) &&
+       test -f "$myidx" &&
+       for p in alt_objects/pack/*.idx; do
+               git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+       done | while read sha1 rest; do
+               if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+                       echo "Missing object in local pack: $sha1"
+                       return 1
+               fi
+       done
+'
+
+test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '
+       rm -f alt_objects/pack/*.keep &&
+       mv .git/objects/pack/* alt_objects/pack/ &&
+       csha1=$(git rev-parse HEAD^{commit}) &&
+       git reset --hard HEAD^ &&
+       sleep 1 &&
+       git reflog expire --expire=now --expire-unreachable=now --all &&
+       # The pack-objects call on the next line is equivalent to
+       # git repack -A -d without the call to prune-packed
+       git pack-objects --honor-pack-keep --non-empty --all --reflog \
+           --unpack-unreachable </dev/null pack &&
+       rm -f .git/objects/pack/* &&
+       mv pack-* .git/objects/pack/ &&
+       test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+               egrep "^$csha1 " | sort | uniq | wc -l) &&
+       echo > .git/objects/info/alternates &&
+       test_must_fail git show $csha1
+'
+
+test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '
+       echo `pwd`/alt_objects > .git/objects/info/alternates &&
+       echo "$csha1" | git pack-objects --non-empty --all --reflog pack &&
+       rm -f .git/objects/pack/* &&
+       mv pack-* .git/objects/pack/ &&
+       # The pack-objects call on the next line is equivalent to
+       # git repack -A -d without the call to prune-packed
+       git pack-objects --honor-pack-keep --non-empty --all --reflog \
+           --unpack-unreachable </dev/null pack &&
+       rm -f .git/objects/pack/* &&
+       mv pack-* .git/objects/pack/ &&
+       test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+               egrep "^$csha1 " | sort | uniq | wc -l) &&
+       echo > .git/objects/info/alternates &&
+       test_must_fail git show $csha1
+'
+
 test_done