]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5314-pack-cycle-detection.sh
The third batch
[thirdparty/git.git] / t / t5314-pack-cycle-detection.sh
CommitLineData
4cf2143e
JK
1#!/bin/sh
2
3test_description='test handling of inter-pack delta cycles during repack
4
5The goal here is to create a situation where we have two blobs, A and B, with A
6as a delta against B in one pack, and vice versa in the other. Then if we can
7persuade a full repack to find A from one pack and B from the other, that will
8give us a cycle when we attempt to reuse those deltas.
9
10The trick is in the "persuade" step, as it depends on the internals of how
11pack-objects picks which pack to reuse the deltas from. But we can assume
12that it does so in one of two general strategies:
13
14 1. Using a static ordering of packs. In this case, no inter-pack cycles can
15 happen. Any objects with a delta relationship must be present in the same
16 pack (i.e., no "--thin" packs on disk), so we will find all related objects
17 from that pack. So assuming there are no cycles within a single pack (and
18 we avoid generating them via pack-objects or importing them via
19 index-pack), then our result will have no cycles.
20
21 So this case should pass the tests no matter how we arrange things.
22
23 2. Picking the next pack to examine based on locality (i.e., where we found
24 something else recently).
25
26 In this case, we want to make sure that we find the delta versions of A and
27 B and not their base versions. We can do this by putting two blobs in each
28 pack. The first is a "dummy" blob that can only be found in the pack in
29 question. And then the second is the actual delta we want to find.
30
31 The two blobs must be present in the same tree, not present in other trees,
32 and the dummy pathname must sort before the delta path.
33
34The setup below focuses on case 2. We have two commits HEAD and HEAD^, each
35which has two files: "dummy" and "file". Then we can make two packs which
36contain:
37
38 [pack one]
39 HEAD:dummy
40 HEAD:file (as delta against HEAD^:file)
41 HEAD^:file (as base)
42
43 [pack two]
44 HEAD^:dummy
45 HEAD^:file (as delta against HEAD:file)
46 HEAD:file (as base)
47
48Then no matter which order we start looking at the packs in, we know that we
49will always find a delta for "file", because its lookup will always come
50immediately after the lookup for "dummy".
51'
4cf2143e 52
27472b51
ÆAB
53TEST_PASSES_SANITIZE_LEAK=true
54. ./test-lib.sh
4cf2143e 55
571fb965 56# Create a pack containing the tree $1 and blob $1:file, with
4cf2143e
JK
57# the latter stored as a delta against $2:file.
58#
59# We convince pack-objects to make the delta in the direction of our choosing
60# by marking $2 as a preferred-base edge. That results in $1:file as a thin
61# delta, and index-pack completes it by adding $2:file as a base.
62#
63# Note that the two variants of "file" must be similar enough to convince git
64# to create the delta.
65make_pack () {
243caa89
ÆAB
66 ln1=$(git rev-parse "$2") &&
67 ln2=$(git rev-parse "$1:dummy") &&
68 ln3=$(git rev-parse "$1:file") &&
69 cat >list <<-EOF
70 -$ln1
71 $ln2 dummy
72 $ln3 file
73 EOF
74 git pack-objects --stdout <list >pack &&
75 git index-pack --stdin --fix-thin <pack
4cf2143e
JK
76}
77
78test_expect_success 'setup' '
c680668d 79 test-tool genrandom base 4096 >base &&
4cf2143e
JK
80 for i in one two
81 do
82 # we want shared content here to encourage deltas...
83 cp base file &&
84 echo $i >>file &&
85
86 # ...whereas dummy should be short, because we do not want
87 # deltas that would create duplicates when we --fix-thin
88 echo $i >dummy &&
89
90 git add file dummy &&
91 test_tick &&
92 git commit -m $i ||
93 return 1
94 done &&
95
96 make_pack HEAD^ HEAD &&
97 make_pack HEAD HEAD^
98'
99
100test_expect_success 'repack' '
101 # We first want to check that we do not have any internal errors,
102 # and also that we do not hit the last-ditch cycle-breaking code
103 # in write_object(), which will issue a warning to stderr.
4cf2143e 104 git repack -ad 2>stderr &&
1c5e94f4 105 test_must_be_empty stderr &&
4cf2143e
JK
106
107 # And then double-check that the resulting pack is usable (i.e.,
108 # we did not fail to notice any cycles). We know we are accessing
109 # the objects via the new pack here, because "repack -d" will have
110 # removed the others.
111 git cat-file blob HEAD:file >/dev/null &&
112 git cat-file blob HEAD^:file >/dev/null
113'
114
115test_done