Merge branch 'sp/missing-thin-base' into maint
authorJunio C Hamano <gitster@pobox.com>
Sat, 30 Aug 2008 15:38:19 +0000 (08:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 30 Aug 2008 15:38:19 +0000 (08:38 -0700)
* sp/missing-thin-base:
pack-objects: Allow missing base objects when creating thin packs

builtin-pack-objects.c
t/t5306-pack-nobase.sh [new file with mode: 0755]
index d394c494a55d45a7af6506371f3432374dffe424..ef3befe57b3b8298798e51627f076e2a40319cb1 100644 (file)
@@ -1095,9 +1095,12 @@ static void check_object(struct object_entry *entry)
        }
 
        entry->type = sha1_object_info(entry->idx.sha1, &entry->size);
-       if (entry->type < 0)
-               die("unable to get type of object %s",
-                   sha1_to_hex(entry->idx.sha1));
+       /*
+        * The error condition is checked in prepare_pack().  This is
+        * to permit a missing preferred base object to be ignored
+        * as a preferred base.  Doing so can result in a larger
+        * pack file, but the transfer will still take place.
+        */
 }
 
 static int pack_offset_sort(const void *_a, const void *_b)
@@ -1721,8 +1724,12 @@ static void prepare_pack(int window, int depth)
                if (entry->no_try_delta)
                        continue;
 
-               if (!entry->preferred_base)
+               if (!entry->preferred_base) {
                        nr_deltas++;
+                       if (entry->type < 0)
+                               die("unable to get type of object %s",
+                                   sha1_to_hex(entry->idx.sha1));
+               }
 
                delta_list[n++] = entry;
        }
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
new file mode 100755 (executable)
index 0000000..f4931c0
--- /dev/null
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Google Inc.
+#
+
+test_description='git-pack-object with missing base
+
+'
+. ./test-lib.sh
+
+# Create A-B chain
+#
+test_expect_success \
+    'setup base' \
+    'for a in a b c d e f g h i; do echo $a >>text; done &&
+     echo side >side &&
+     git update-index --add text side &&
+     A=$(echo A | git commit-tree $(git write-tree)) &&
+
+     echo m >>text &&
+     git update-index text &&
+     B=$(echo B | git commit-tree $(git write-tree) -p $A) &&
+     git update-ref HEAD $B
+    '
+
+# Create repository with C whose parent is B.
+# Repository contains C, C^{tree}, C:text, B, B^{tree}.
+# Repository is missing B:text (best delta base for C:text).
+# Repository is missing A (parent of B).
+# Repository is missing A:side.
+#
+test_expect_success \
+    'setup patch_clone' \
+    'base_objects=$(pwd)/.git/objects &&
+     (mkdir patch_clone &&
+      cd patch_clone &&
+      git init &&
+      echo "$base_objects" >.git/objects/info/alternates &&
+      echo q >>text &&
+      git read-tree $B &&
+      git update-index text &&
+      git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) &&
+      rm .git/objects/info/alternates &&
+
+      git --git-dir=../.git cat-file commit $B |
+      git hash-object -t commit -w --stdin &&
+
+      git --git-dir=../.git cat-file tree "$B^{tree}" |
+      git hash-object -t tree -w --stdin
+     ) &&
+     C=$(git --git-dir=patch_clone/.git rev-parse HEAD)
+    '
+
+# Clone patch_clone indirectly by cloning base and fetching.
+#
+test_expect_success \
+    'indirectly clone patch_clone' \
+    '(mkdir user_clone &&
+      cd user_clone &&
+      git init &&
+      git pull ../.git &&
+      test $(git rev-parse HEAD) = $B &&
+
+      git pull ../patch_clone/.git &&
+      test $(git rev-parse HEAD) = $C
+     )
+    '
+
+# Cloning the patch_clone directly should fail.
+#
+test_expect_success \
+    'clone of patch_clone is incomplete' \
+    '(mkdir user_direct &&
+      cd user_direct &&
+      git init &&
+      test_must_fail git fetch ../patch_clone/.git
+     )
+    '
+
+test_done