summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2013-06-23 14:53:20 -0700
committerJunio C Hamano <gitster@pobox.com>2013-06-23 14:53:20 -0700
commitee64e345b1ac13cbb9c6a2343453fa3fc798367a (patch)
treef410dbf23e0cb15a71e853358b8610b470360121
parent23983a473dc889cfba8a64f040942298a6f5f99a (diff)
parent1ee886c1f08f4dd672a342b7811191b02291a597 (diff)
downloadgit-ee64e345b1ac13cbb9c6a2343453fa3fc798367a.tar.gz
Merge branch 'jk/unpack-entry-fallback-to-another'
* jk/unpack-entry-fallback-to-another: unpack_entry: do not die when we fail to apply a delta t5303: drop "count=1" from corruption dd
-rw-r--r--sha1_file.c11
-rwxr-xr-xt/t5303-pack-corruption-resilience.sh29
2 files changed, 38 insertions, 2 deletions
diff --git a/sha1_file.c b/sha1_file.c
index 16f08d475c..0af19c00f1 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2145,8 +2145,17 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
data = patch_delta(base, base_size,
delta_data, delta_size,
&size);
+
+ /*
+ * We could not apply the delta; warn the user, but keep going.
+ * Our failure will be noticed either in the next iteration of
+ * the loop, or if this is the final delta, in the caller when
+ * we return NULL. Those code paths will take care of making
+ * a more explicit warning and retrying with another copy of
+ * the object.
+ */
if (!data)
- die("failed to apply delta");
+ error("failed to apply delta");
free(delta_data);
}
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
index 5b1250f0d2..35926debe3 100755
--- a/t/t5303-pack-corruption-resilience.sh
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -51,7 +51,7 @@ do_corrupt_object() {
ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
ofs=$(($ofs + $2)) &&
chmod +w ${pack}.pack &&
- dd of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
+ dd of=${pack}.pack bs=1 conv=notrunc seek=$ofs &&
test_must_fail git verify-pack ${pack}.pack
}
@@ -276,6 +276,33 @@ test_expect_success \
git cat-file blob $blob_3 > /dev/null'
test_expect_success \
+ 'corruption of delta base reference pointing to wrong object' \
+ 'create_new_pack --delta-base-offset &&
+ git prune-packed &&
+ printf "\220\033" | do_corrupt_object $blob_3 2 &&
+ git cat-file blob $blob_1 >/dev/null &&
+ git cat-file blob $blob_2 >/dev/null &&
+ test_must_fail git cat-file blob $blob_3 >/dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_3 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack --delta-base-offset --no-reuse-delta &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
'corrupting header to have too small output buffer fails unpack' \
'create_new_pack &&
git prune-packed &&