Git fork
1#!/bin/sh
2
3test_description='see how we handle various forms of corruption'
4
5. ./test-lib.sh
6
7# convert "1234abcd" to ".git/objects/12/34abcd"
8obj_to_file() {
9 echo "$(git rev-parse --git-dir)/objects/$(git rev-parse "$1" | sed 's,..,&/,')"
10}
11
12# Convert byte at offset "$2" of object "$1" into '\0'
13corrupt_byte() {
14 obj_file=$(obj_to_file "$1") &&
15 chmod +w "$obj_file" &&
16 printf '\0' | dd of="$obj_file" bs=1 seek="$2" conv=notrunc
17}
18
19test_expect_success 'setup corrupt repo' '
20 git init bit-error &&
21 (
22 cd bit-error &&
23 test_commit content &&
24 corrupt_byte HEAD:content.t 10
25 ) &&
26 git init no-bit-error &&
27 (
28 # distinct commit from bit-error, but containing a
29 # non-corrupted version of the same blob
30 cd no-bit-error &&
31 test_tick &&
32 test_commit content
33 )
34'
35
36test_expect_success 'setup repo with missing object' '
37 git init missing &&
38 (
39 cd missing &&
40 test_commit content &&
41 rm -f "$(obj_to_file HEAD:content.t)"
42 )
43'
44
45test_expect_success 'setup repo with misnamed object' '
46 git init misnamed &&
47 (
48 cd misnamed &&
49 test_commit content &&
50 good=$(obj_to_file HEAD:content.t) &&
51 blob=$(echo corrupt | git hash-object -w --stdin) &&
52 bad=$(obj_to_file $blob) &&
53 rm -f "$good" &&
54 mv "$bad" "$good"
55 )
56'
57
58test_expect_success 'streaming a corrupt blob fails' '
59 (
60 cd bit-error &&
61 test_must_fail git cat-file blob HEAD:content.t
62 )
63'
64
65test_expect_success 'getting type of a corrupt blob fails' '
66 (
67 cd bit-error &&
68 test_must_fail git cat-file -s HEAD:content.t
69 )
70'
71
72test_expect_success 'read-tree -u detects bit-errors in blobs' '
73 (
74 cd bit-error &&
75 rm -f content.t &&
76 test_must_fail git read-tree --reset -u HEAD
77 )
78'
79
80test_expect_success 'read-tree -u detects missing objects' '
81 (
82 cd missing &&
83 rm -f content.t &&
84 test_must_fail git read-tree --reset -u HEAD
85 )
86'
87
88# We use --bare to make sure that the transport detects it, not the checkout
89# phase.
90test_expect_success 'clone --no-local --bare detects corruption' '
91 test_must_fail git clone --no-local --bare bit-error corrupt-transport
92'
93
94test_expect_success 'clone --no-local --bare detects missing object' '
95 test_must_fail git clone --no-local --bare missing missing-transport
96'
97
98test_expect_success 'clone --no-local --bare detects misnamed object' '
99 test_must_fail git clone --no-local --bare misnamed misnamed-transport
100'
101
102# We do not expect --local to detect corruption at the transport layer,
103# so we are really checking the checkout() code path.
104test_expect_success 'clone --local detects corruption' '
105 test_must_fail git clone --local bit-error corrupt-checkout
106'
107
108test_expect_success 'error detected during checkout leaves repo intact' '
109 test_path_is_dir corrupt-checkout/.git
110'
111
112test_expect_success 'clone --local detects missing objects' '
113 test_must_fail git clone --local missing missing-checkout
114'
115
116test_expect_failure 'clone --local detects misnamed objects' '
117 test_must_fail git clone --local misnamed misnamed-checkout
118'
119
120test_expect_success 'fetch into corrupted repo with index-pack' '
121 cp -R bit-error bit-error-cp &&
122 test_when_finished "rm -rf bit-error-cp" &&
123 (
124 cd bit-error-cp &&
125 test_must_fail git -c transfer.unpackLimit=1 \
126 fetch ../no-bit-error 2>stderr &&
127 test_grep ! -i collision stderr
128 )
129'
130
131test_expect_success 'internal tree objects are not "missing"' '
132 git init missing-empty &&
133 (
134 cd missing-empty &&
135 empty_tree=$(git hash-object -t tree /dev/null) &&
136 commit=$(echo foo | git commit-tree $empty_tree) &&
137 git rev-list --objects $commit
138 )
139'
140
141test_expect_success 'partial clone of corrupted repository' '
142 test_config -C misnamed uploadpack.allowFilter true &&
143 git clone --no-local --no-checkout --filter=blob:none \
144 misnamed corrupt-partial && \
145 test_must_fail git -C corrupt-partial checkout --force
146'
147
148test_done