a21781011f
When we're resolving a REF_DELTA, we compare-and-swap its type from REF_DELTA to whatever real type the base object has, as discussed inab791dd138
(index-pack: fix race condition with duplicate bases, 2014-08-29). If the old type wasn't a REF_DELTA, we consider that a BUG(). But as discussed in that commit, we might see this case whenever we try to resolve an object twice, which may happen because we have multiple copies of the base object. So this isn't a bug at all, but rather a sign that the input pack is broken. And indeed, this case is triggered already in t5309.5 and t5309.6, which create packs with delta cycles and duplicate bases. But we never noticed because those tests are marked expect_failure. Those tests were added byb2ef3d9ebb
(test index-pack on packs with recoverable delta cycles, 2013-08-23), which was leaving the door open for cases that we theoretically _could_ handle. And when we see an already-resolved object like this, in theory we could keep going after confirming that the previously resolved child->real_type matches base->obj->real_type. But: - enforcing the "only resolve once" rule here saves us from an infinite loop in other parts of the code. If we keep going, then the delta cycle in t5309.5 causes us to loop infinitely, as find_ref_delta_children() doesn't realize which objects have already been resolved. So there would be more changes needed to make this case work, and in the meantime we'd be worse off. - any pack that triggers this is broken anyway. It either has a duplicate base object, or it has a cycle which causes us to bring in a duplicate via --fix-thin. In either case, we'd end up rejecting the pack in write_idx_file(), which also detects duplicates. So the tests have little value in documenting what we _could_ be doing (and have been neglected for 6+ years). Let's switch them to confirming that we handle this case cleanly (and switch out the BUG() for a more informative die() so that we do so). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
84 lines
1.9 KiB
Bash
Executable File
84 lines
1.9 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='test index-pack handling of delta cycles in packfiles'
|
|
. ./test-lib.sh
|
|
. "$TEST_DIRECTORY"/lib-pack.sh
|
|
|
|
if ! test_have_prereq SHA1
|
|
then
|
|
skip_all='not using SHA-1 for objects'
|
|
test_done
|
|
fi
|
|
|
|
# Two similar-ish objects that we have computed deltas between.
|
|
A=01d7713666f4de822776c7622c10f1b07de280dc
|
|
B=e68fe8129b546b101aee9510c5328e7f21ca1d18
|
|
|
|
# double-check our hand-constucted packs
|
|
test_expect_success 'index-pack works with a single delta (A->B)' '
|
|
clear_packs &&
|
|
{
|
|
pack_header 2 &&
|
|
pack_obj $A $B &&
|
|
pack_obj $B
|
|
} >ab.pack &&
|
|
pack_trailer ab.pack &&
|
|
git index-pack --stdin <ab.pack &&
|
|
git cat-file -t $A &&
|
|
git cat-file -t $B
|
|
'
|
|
|
|
test_expect_success 'index-pack works with a single delta (B->A)' '
|
|
clear_packs &&
|
|
{
|
|
pack_header 2 &&
|
|
pack_obj $A &&
|
|
pack_obj $B $A
|
|
} >ba.pack &&
|
|
pack_trailer ba.pack &&
|
|
git index-pack --stdin <ba.pack &&
|
|
git cat-file -t $A &&
|
|
git cat-file -t $B
|
|
'
|
|
|
|
test_expect_success 'index-pack detects missing base objects' '
|
|
clear_packs &&
|
|
{
|
|
pack_header 1 &&
|
|
pack_obj $A $B
|
|
} >missing.pack &&
|
|
pack_trailer missing.pack &&
|
|
test_must_fail git index-pack --fix-thin --stdin <missing.pack
|
|
'
|
|
|
|
test_expect_success 'index-pack detects REF_DELTA cycles' '
|
|
clear_packs &&
|
|
{
|
|
pack_header 2 &&
|
|
pack_obj $A $B &&
|
|
pack_obj $B $A
|
|
} >cycle.pack &&
|
|
pack_trailer cycle.pack &&
|
|
test_must_fail git index-pack --fix-thin --stdin <cycle.pack
|
|
'
|
|
|
|
test_expect_success 'failover to an object in another pack' '
|
|
clear_packs &&
|
|
git index-pack --stdin <ab.pack &&
|
|
test_must_fail git index-pack --stdin --fix-thin <cycle.pack
|
|
'
|
|
|
|
test_expect_success 'failover to a duplicate object in the same pack' '
|
|
clear_packs &&
|
|
{
|
|
pack_header 3 &&
|
|
pack_obj $A $B &&
|
|
pack_obj $B $A &&
|
|
pack_obj $A
|
|
} >recoverable.pack &&
|
|
pack_trailer recoverable.pack &&
|
|
test_must_fail git index-pack --fix-thin --stdin <recoverable.pack
|
|
'
|
|
|
|
test_done
|