]> git.ipfire.org Git - thirdparty/git.git/blame - t/t1512-rev-parse-disambiguation.sh
The third batch
[thirdparty/git.git] / t / t1512-rev-parse-disambiguation.sh
CommitLineData
6269b6b6
JH
1#!/bin/sh
2
3test_description='object name disambiguation
4
5Create blobs, trees, commits and a tag that all share the same
6prefix, and make sure "git rev-parse" can take advantage of
7type information to disambiguate short object names that are
8not necessarily unique.
9
10The final history used in the test has five commits, with the bottom
11one tagged as v1.0.0. They all have one regular file each.
12
13 +-------------------------------------------+
14 | |
15 | .-------b3wettvi---- ad2uee |
16 | / / |
17 | a2onsxbvj---czy8f73t--ioiley5o |
18 | |
19 +-------------------------------------------+
20
21'
22
06d53148 23GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
334afbc7
JS
24export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
25
6269b6b6
JH
26. ./test-lib.sh
27
8d56136d
ÆAB
28test_cmp_failed_rev_parse () {
29 dir=$1
30 rev=$2
31
32 cat >expect &&
33 test_must_fail git -C "$dir" rev-parse "$rev" 2>actual.raw &&
34 sed "s/\($rev\)[0-9a-f]*/\1.../" <actual.raw >actual &&
35 test_cmp expect actual
36}
37
38test_expect_success 'ambiguous blob output' '
39 git init --bare blob.prefix &&
40 (
41 cd blob.prefix &&
42
43 # Both start with "dead..", under both SHA-1 and SHA-256
44 echo brocdnra | git hash-object -w --stdin &&
45 echo brigddsv | git hash-object -w --stdin &&
46
47 # Both start with "beef.."
48 echo 1agllotbh | git hash-object -w --stdin &&
49 echo 1bbfctrkc | git hash-object -w --stdin
50 ) &&
51
52 test_must_fail git -C blob.prefix rev-parse dead &&
53 test_cmp_failed_rev_parse blob.prefix beef <<-\EOF
54 error: short object ID beef... is ambiguous
55 hint: The candidates are:
56 hint: beef... blob
57 hint: beef... blob
58 fatal: ambiguous argument '\''beef...'\'': unknown revision or path not in the working tree.
59 Use '\''--'\'' to separate paths from revisions, like this:
60 '\''git <command> [<revision>...] -- [<file>...]'\''
61 EOF
62'
63
64test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' '
65 git init --bare blob.bad &&
66 (
67 cd blob.bad &&
68
69 # Both have the prefix "bad0"
70 echo xyzfaowcoh | git hash-object -t bad -w --stdin --literally &&
71 echo xyzhjpyvwl | git hash-object -t bad -w --stdin --literally
72 ) &&
73
74 test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF
75 error: short object ID bad0... is ambiguous
8d56136d
ÆAB
76 fatal: invalid object type
77 EOF
78'
79
80test_expect_success POSIXPERM 'ambigous zlib corrupt loose blob' '
81 git init --bare blob.corrupt &&
82 (
83 cd blob.corrupt &&
84
85 # Both have the prefix "cafe"
86 echo bnkxmdwz | git hash-object -w --stdin &&
87 oid=$(echo bmwsjxzi | git hash-object -w --stdin) &&
88
89 oidf=objects/$(test_oid_to_path "$oid") &&
90 chmod 755 $oidf &&
91 echo broken >$oidf
92 ) &&
93
94 test_cmp_failed_rev_parse blob.corrupt cafe <<-\EOF
95 error: short object ID cafe... is ambiguous
8d56136d
ÆAB
96 error: inflate: data stream error (incorrect header check)
97 error: unable to unpack cafe... header
98 error: inflate: data stream error (incorrect header check)
99 error: unable to unpack cafe... header
d2ef3cb7 100 hint: The candidates are:
6780e680 101 hint: cafe... [bad object]
8d56136d
ÆAB
102 hint: cafe... blob
103 fatal: ambiguous argument '\''cafe...'\'': unknown revision or path not in the working tree.
104 Use '\''--'\'' to separate paths from revisions, like this:
105 '\''git <command> [<revision>...] -- [<file>...]'\''
106 EOF
107'
108
d7a2fc82 109if ! test_have_prereq SHA1
110then
111 skip_all='not using SHA-1 for objects'
112 test_done
113fi
114
6269b6b6
JH
115test_expect_success 'blob and tree' '
116 test_tick &&
117 (
08495412 118 test_write_lines 0 1 2 3 4 5 6 7 8 9 &&
f2deabfc 119 echo &&
6269b6b6
JH
120 echo b1rwzyc3
121 ) >a0blgqsjc &&
122
123 # create one blob 0000000000b36
124 git add a0blgqsjc &&
125
126 # create one tree 0000000000cdc
127 git write-tree
128'
129
130test_expect_success 'warn ambiguity when no candidate matches type hint' '
131 test_must_fail git rev-parse --verify 000000000^{commit} 2>actual &&
6789275d 132 test_grep "short object ID 000000000 is ambiguous" actual
6269b6b6
JH
133'
134
daba53ae 135test_expect_success 'disambiguate tree-ish' '
6269b6b6
JH
136 # feed tree-ish in an unambiguous way
137 git rev-parse --verify 0000000000cdc:a0blgqsjc &&
138
139 # ambiguous at the object name level, but there is only one
140 # such tree-ish (the other is a blob)
141 git rev-parse --verify 000000000:a0blgqsjc
142'
143
da3ac0c1 144test_expect_success 'disambiguate blob' '
6269b6b6
JH
145 sed -e "s/|$//" >patch <<-EOF &&
146 diff --git a/frotz b/frotz
147 index 000000000..ffffff 100644
148 --- a/frotz
149 +++ b/frotz
150 @@ -10,3 +10,4 @@
151 9
152 |
153 b1rwzyc3
154 +irwry
155 EOF
156 (
157 GIT_INDEX_FILE=frotz &&
158 export GIT_INDEX_FILE &&
159 git apply --build-fake-ancestor frotz patch &&
160 git cat-file blob :frotz >actual
161 ) &&
162 test_cmp a0blgqsjc actual
163'
164
75f5ac04 165test_expect_success 'disambiguate tree' '
6269b6b6 166 commit=$(echo "d7xm" | git commit-tree 000000000) &&
2c57f7c9 167 # this commit is fffff2e and not ambiguous with the 00000* objects
6269b6b6
JH
168 test $(git rev-parse $commit^{tree}) = $(git rev-parse 0000000000cdc)
169'
170
171test_expect_success 'first commit' '
172 # create one commit 0000000000e4f
173 git commit -m a2onsxbvj
174'
175
e2643617 176test_expect_success 'disambiguate commit-ish' '
6269b6b6
JH
177 # feed commit-ish in an unambiguous way
178 git rev-parse --verify 0000000000e4f^{commit} &&
179
180 # ambiguous at the object name level, but there is only one
181 # such commit (the others are tree and blob)
182 git rev-parse --verify 000000000^{commit} &&
183
184 # likewise
185 git rev-parse --verify 000000000^0
186'
187
75f5ac04 188test_expect_success 'disambiguate commit' '
31ffd0c0 189 commit=$(echo "hoaxj" | git commit-tree 0000000000cdc -p 000000000) &&
2c57f7c9 190 # this commit is ffffffd8 and not ambiguous with the 00000* objects
6269b6b6
JH
191 test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f)
192'
193
cd74e473 194test_expect_success 'log name1..name2 takes only commit-ishes on both ends' '
2c57f7c9
JH
195 # These are underspecified from the prefix-length point of view
196 # to disambiguate the commit with other objects, but there is only
197 # one commit that has 00000* prefix at this point.
6269b6b6
JH
198 git log 000000000..000000000 &&
199 git log ..000000000 &&
200 git log 000000000.. &&
201 git log 000000000...000000000 &&
202 git log ...000000000 &&
203 git log 000000000...
204'
205
c036c4c5 206test_expect_success 'rev-parse name1..name2 takes only commit-ishes on both ends' '
2c57f7c9 207 # Likewise.
6269b6b6
JH
208 git rev-parse 000000000..000000000 &&
209 git rev-parse ..000000000 &&
210 git rev-parse 000000000..
211'
212
d5f6b1d7 213test_expect_success 'git log takes only commit-ish' '
2c57f7c9 214 # Likewise.
6269b6b6
JH
215 git log 000000000
216'
217
13243c2c 218test_expect_success 'git reset takes only commit-ish' '
2c57f7c9 219 # Likewise.
6269b6b6
JH
220 git reset 000000000
221'
222
223test_expect_success 'first tag' '
224 # create one tag 0000000000f8f
225 git tag -a -m j7cp83um v1.0.0
226'
227
228test_expect_failure 'two semi-ambiguous commit-ish' '
2c57f7c9
JH
229 # At this point, we have a tag 0000000000f8f that points
230 # at a commit 0000000000e4f, and a tree and a blob that
231 # share 0000000000 prefix with these tag and commit.
232 #
6269b6b6 233 # Once the parser becomes ultra-smart, it could notice that
2c57f7c9 234 # 0000000000 before ^{commit} name many different objects, but
6269b6b6
JH
235 # that only two (HEAD and v1.0.0 tag) can be peeled to commit,
236 # and that peeling them down to commit yield the same commit
237 # without ambiguity.
2c57f7c9 238 git rev-parse --verify 0000000000^{commit} &&
6269b6b6
JH
239
240 # likewise
2c57f7c9
JH
241 git log 0000000000..0000000000 &&
242 git log ..0000000000 &&
243 git log 0000000000.. &&
244 git log 0000000000...0000000000 &&
245 git log ...0000000000 &&
246 git log 0000000000...
6269b6b6
JH
247'
248
249test_expect_failure 'three semi-ambiguous tree-ish' '
250 # Likewise for tree-ish. HEAD, v1.0.0 and HEAD^{tree} share
251 # the prefix but peeling them to tree yields the same thing
2c57f7c9 252 git rev-parse --verify 0000000000^{tree}
6269b6b6
JH
253'
254
255test_expect_success 'parse describe name' '
256 # feed an unambiguous describe name
257 git rev-parse --verify v1.0.0-0-g0000000000e4f &&
258
259 # ambiguous at the object name level, but there is only one
260 # such commit (others are blob, tree and tag)
261 git rev-parse --verify v1.0.0-0-g000000000
262'
263
264test_expect_success 'more history' '
265 # commit 0000000000043
266 git mv a0blgqsjc d12cr3h8t &&
267 echo h62xsjeu >>d12cr3h8t &&
268 git add d12cr3h8t &&
269
270 test_tick &&
271 git commit -m czy8f73t &&
272
273 # commit 00000000008ec
274 git mv d12cr3h8t j000jmpzn &&
275 echo j08bekfvt >>j000jmpzn &&
276 git add j000jmpzn &&
277
278 test_tick &&
279 git commit -m ioiley5o &&
280
281 # commit 0000000005b0
282 git checkout v1.0.0^0 &&
283 git mv a0blgqsjc f5518nwu &&
284
08495412 285 test_write_lines h62xsjeu j08bekfvt kg7xflhm >>f5518nwu &&
6269b6b6
JH
286 git add f5518nwu &&
287
288 test_tick &&
289 git commit -m b3wettvi &&
290 side=$(git rev-parse HEAD) &&
291
292 # commit 000000000066
06d53148 293 git checkout main &&
6269b6b6
JH
294
295 # If you use recursive, merge will fail and you will need to
296 # clean up a0blgqsjc as well. If you use resolve, merge will
297 # succeed.
298 test_might_fail git merge --no-commit -s recursive $side &&
299 git rm -f f5518nwu j000jmpzn &&
300
301 test_might_fail git rm -f a0blgqsjc &&
302 (
f2deabfc 303 git cat-file blob $side:f5518nwu &&
6269b6b6
JH
304 echo j3l0i9s6
305 ) >ab2gs879 &&
306 git add ab2gs879 &&
307
308 test_tick &&
309 git commit -m ad2uee
310
311'
312
313test_expect_failure 'parse describe name taking advantage of generation' '
314 # ambiguous at the object name level, but there is only one
315 # such commit at generation 0
316 git rev-parse --verify v1.0.0-0-g000000000 &&
317
318 # likewise for generation 2 and 4
319 git rev-parse --verify v1.0.0-2-g000000000 &&
320 git rev-parse --verify v1.0.0-4-g000000000
321'
322
323# Note: because rev-parse does not even try to disambiguate based on
324# the generation number, this test currently succeeds for a wrong
325# reason. When it learns to use the generation number, the previous
326# test should succeed, and also this test should fail because the
327# describe name used in the test with generation number can name two
328# commits. Make sure that such a future enhancement does not randomly
329# pick one.
330test_expect_success 'parse describe name not ignoring ambiguity' '
331 # ambiguous at the object name level, and there are two such
332 # commits at generation 1
333 test_must_fail git rev-parse --verify v1.0.0-1-g000000000
334'
335
336test_expect_success 'ambiguous commit-ish' '
337 # Now there are many commits that begin with the
338 # common prefix, none of these should pick one at
339 # random. They all should result in ambiguity errors.
2c57f7c9 340 test_must_fail git rev-parse --verify 00000000^{commit} &&
6269b6b6
JH
341
342 # likewise
343 test_must_fail git log 000000000..000000000 &&
344 test_must_fail git log ..000000000 &&
345 test_must_fail git log 000000000.. &&
346 test_must_fail git log 000000000...000000000 &&
347 test_must_fail git log ...000000000 &&
348 test_must_fail git log 000000000...
349'
350
5d5def2a
JK
351# There are three objects with this prefix: a blob, a tree, and a tag. We know
352# the blob will not pass as a treeish, but the tree and tag should (and thus
353# cause an error).
354test_expect_success 'ambiguous tags peel to treeish' '
355 test_must_fail git rev-parse 0000000000f^{tree}
356'
357
957d7406
JH
358test_expect_success 'rev-parse --disambiguate' '
359 # The test creates 16 objects that share the prefix and two
31ffd0c0
JH
360 # commits created by commit-tree in earlier tests share a
361 # different prefix.
957d7406 362 git rev-parse --disambiguate=000000000 >actual &&
a5d04a3e 363 test_line_count = 16 actual &&
957d7406
JH
364 test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000
365'
366
fad6b9e5
JK
367test_expect_success 'rev-parse --disambiguate drops duplicates' '
368 git rev-parse --disambiguate=000000000 >expect &&
369 git pack-objects .git/objects/pack/pack <expect &&
370 git rev-parse --disambiguate=000000000 >actual &&
371 test_cmp expect actual
372'
373
798c35fc
NTND
374test_expect_success 'ambiguous 40-hex ref' '
375 TREE=$(git mktree </dev/null) &&
dcfbb2aa 376 REF=$(git rev-parse HEAD) &&
798c35fc
NTND
377 VAL=$(git commit-tree $TREE </dev/null) &&
378 git update-ref refs/heads/$REF $VAL &&
dcfbb2aa 379 test $(git rev-parse $REF 2>err) = $REF &&
798c35fc
NTND
380 grep "refname.*${REF}.*ambiguous" err
381'
382
383test_expect_success 'ambiguous short sha1 ref' '
384 TREE=$(git mktree </dev/null) &&
dcfbb2aa 385 REF=$(git rev-parse --short HEAD) &&
798c35fc
NTND
386 VAL=$(git commit-tree $TREE </dev/null) &&
387 git update-ref refs/heads/$REF $VAL &&
dcfbb2aa 388 test $(git rev-parse $REF 2>err) = $VAL &&
798c35fc
NTND
389 grep "refname.*${REF}.*ambiguous" err
390'
391
a926c4b9 392test_expect_success 'ambiguity errors are not repeated (raw)' '
7243ffdd
JK
393 test_must_fail git rev-parse 00000 2>stderr &&
394 grep "is ambiguous" stderr >errors &&
395 test_line_count = 1 errors
396'
397
a926c4b9 398test_expect_success 'ambiguity errors are not repeated (treeish)' '
8a10fea4
JK
399 test_must_fail git rev-parse 00000:foo 2>stderr &&
400 grep "is ambiguous" stderr >errors &&
401 test_line_count = 1 errors
402'
403
a926c4b9 404test_expect_success 'ambiguity errors are not repeated (peel)' '
8a10fea4
JK
405 test_must_fail git rev-parse 00000^{commit} 2>stderr &&
406 grep "is ambiguous" stderr >errors &&
407 test_line_count = 1 errors
408'
409
a926c4b9 410test_expect_success 'ambiguity hints' '
1ffa26c4
JK
411 test_must_fail git rev-parse 000000000 2>stderr &&
412 grep ^hint: stderr >hints &&
413 # 16 candidates, plus one intro line
414 test_line_count = 17 hints
415'
416
a926c4b9 417test_expect_success 'ambiguity hints respect type' '
1ffa26c4
JK
418 test_must_fail git rev-parse 000000000^{commit} 2>stderr &&
419 grep ^hint: stderr >hints &&
7a40cf15 420 # 5 commits, 1 tag (which is a committish), plus intro line
1ffa26c4
JK
421 test_line_count = 7 hints
422'
423
a926c4b9 424test_expect_success 'failed type-selector still shows hint' '
1ffa26c4
JK
425 # these two blobs share the same prefix "ee3d", but neither
426 # will pass for a commit
427 echo 851 | git hash-object --stdin -w &&
428 echo 872 | git hash-object --stdin -w &&
429 test_must_fail git rev-parse ee3d^{commit} 2>stderr &&
430 grep ^hint: stderr >hints &&
431 test_line_count = 3 hints
432'
433
5b33cb1f
JK
434test_expect_success 'core.disambiguate config can prefer types' '
435 # ambiguous between tree and tag
436 sha1=0000000000f &&
437 test_must_fail git rev-parse $sha1 &&
438 git rev-parse $sha1^{commit} &&
439 git -c core.disambiguate=committish rev-parse $sha1
440'
441
442test_expect_success 'core.disambiguate does not override context' '
443 # treeish ambiguous between tag and tree
444 test_must_fail \
445 git -c core.disambiguate=committish rev-parse $sha1^{tree}
446'
447
a926c4b9 448test_expect_success 'ambiguous commits are printed by type first, then hash order' '
5cc044e0
ÆAB
449 test_must_fail git rev-parse 0000 2>stderr &&
450 grep ^hint: stderr >hints &&
451 grep 0000 hints >objects &&
452 cat >expected <<-\EOF &&
453 tag
454 commit
455 tree
456 blob
457 EOF
458 awk "{print \$3}" <objects >objects.types &&
459 uniq <objects.types >objects.types.uniq &&
460 test_cmp expected objects.types.uniq &&
461 for type in tag commit tree blob
462 do
463 grep $type objects >$type.objects &&
464 sort $type.objects >$type.objects.sorted &&
db5875aa 465 test_cmp $type.objects.sorted $type.objects || return 1
5cc044e0
ÆAB
466 done
467'
468
df799f5d
EW
469test_expect_success 'cat-file --batch and --batch-check show ambiguous' '
470 echo "0000 ambiguous" >expect &&
471 echo 0000 | git cat-file --batch-check >actual 2>err &&
472 test_cmp expect actual &&
6789275d 473 test_grep hint: err &&
df799f5d
EW
474 echo 0000 | git cat-file --batch >actual 2>err &&
475 test_cmp expect actual &&
6789275d 476 test_grep hint: err
df799f5d
EW
477'
478
6269b6b6 479test_done