Git 2.45
[git/gitster.git] / t / t1006-cat-file.sh
blobe12b2219721c4e9e1f29dd5eeb2e9b787d9b78db
1 #!/bin/sh
3 test_description='git cat-file'
5 . ./test-lib.sh
7 test_cmdmode_usage () {
8 test_expect_code 129 "$@" 2>err &&
9 grep "^error: .* cannot be used together" err
12 for switches in \
13 '-e -p' \
14 '-p -t' \
15 '-t -s' \
16 '-s --textconv' \
17 '--textconv --filters' \
18 '--batch-all-objects -e'
20 test_expect_success "usage: cmdmode $switches" '
21 test_cmdmode_usage git cat-file $switches
23 done
25 test_incompatible_usage () {
26 test_expect_code 129 "$@" 2>err &&
27 grep -E "^(fatal|error):.*(requires|incompatible with|needs)" err
30 for opt in --batch --batch-check
32 test_expect_success "usage: incompatible options: --path with $opt" '
33 test_incompatible_usage git cat-file --path=foo $opt
35 done
37 test_missing_usage () {
38 test_expect_code 129 "$@" 2>err &&
39 grep -E "^fatal:.*required" err
42 short_modes="-e -p -t -s"
43 cw_modes="--textconv --filters"
45 for opt in $cw_modes
47 test_expect_success "usage: $opt requires another option" '
48 test_missing_usage git cat-file $opt
50 done
52 for opt in $short_modes
54 test_expect_success "usage: $opt requires another option" '
55 test_missing_usage git cat-file $opt
58 for opt2 in --batch \
59 --batch-check \
60 --follow-symlinks \
61 "--path=foo HEAD:some-path.txt"
63 test_expect_success "usage: incompatible options: $opt and $opt2" '
64 test_incompatible_usage git cat-file $opt $opt2
66 done
67 done
69 test_too_many_arguments () {
70 test_expect_code 129 "$@" 2>err &&
71 grep -E "^fatal: too many arguments$" err
74 for opt in $short_modes $cw_modes
76 args="one two three"
77 test_expect_success "usage: too many arguments: $opt $args" '
78 test_too_many_arguments git cat-file $opt $args
81 for opt2 in --buffer --follow-symlinks
83 test_expect_success "usage: incompatible arguments: $opt with batch option $opt2" '
84 test_incompatible_usage git cat-file $opt $opt2
86 done
87 done
89 for opt in --buffer \
90 --follow-symlinks \
91 --batch-all-objects \
92 -z \
95 test_expect_success "usage: bad option combination: $opt without batch mode" '
96 test_incompatible_usage git cat-file $opt &&
97 test_incompatible_usage git cat-file $opt commit HEAD
99 done
101 echo_without_newline () {
102 printf '%s' "$*"
105 echo_without_newline_nul () {
106 echo_without_newline "$@" | tr '\n' '\0'
109 strlen () {
110 echo_without_newline "$1" | wc -c | sed -e 's/^ *//'
113 run_tests () {
114 type=$1
115 oid=$2
116 size=$3
117 content=$4
118 pretty_content=$5
120 batch_output="$oid $type $size
121 $content"
123 test_expect_success "$type exists" '
124 git cat-file -e $oid
127 test_expect_success "Type of $type is correct" '
128 echo $type >expect &&
129 git cat-file -t $oid >actual &&
130 test_cmp expect actual
133 test_expect_success "Size of $type is correct" '
134 echo $size >expect &&
135 git cat-file -s $oid >actual &&
136 test_cmp expect actual
139 test_expect_success "Type of $type is correct using --allow-unknown-type" '
140 echo $type >expect &&
141 git cat-file -t --allow-unknown-type $oid >actual &&
142 test_cmp expect actual
145 test_expect_success "Size of $type is correct using --allow-unknown-type" '
146 echo $size >expect &&
147 git cat-file -s --allow-unknown-type $oid >actual &&
148 test_cmp expect actual
151 test -z "$content" ||
152 test_expect_success "Content of $type is correct" '
153 echo_without_newline "$content" >expect &&
154 git cat-file $type $oid >actual &&
155 test_cmp expect actual
158 test_expect_success "Pretty content of $type is correct" '
159 echo_without_newline "$pretty_content" >expect &&
160 git cat-file -p $oid >actual &&
161 test_cmp expect actual
164 test -z "$content" ||
165 test_expect_success "--batch output of $type is correct" '
166 echo "$batch_output" >expect &&
167 echo $oid | git cat-file --batch >actual &&
168 test_cmp expect actual
171 test_expect_success "--batch-check output of $type is correct" '
172 echo "$oid $type $size" >expect &&
173 echo_without_newline $oid | git cat-file --batch-check >actual &&
174 test_cmp expect actual
177 for opt in --buffer --no-buffer
179 test -z "$content" ||
180 test_expect_success "--batch-command $opt output of $type content is correct" '
181 echo "$batch_output" >expect &&
182 test_write_lines "contents $oid" | git cat-file --batch-command $opt >actual &&
183 test_cmp expect actual
186 test_expect_success "--batch-command $opt output of $type info is correct" '
187 echo "$oid $type $size" >expect &&
188 test_write_lines "info $oid" |
189 git cat-file --batch-command $opt >actual &&
190 test_cmp expect actual
192 done
194 test_expect_success "custom --batch-check format" '
195 echo "$type $oid" >expect &&
196 echo $oid | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&
197 test_cmp expect actual
200 test_expect_success "custom --batch-command format" '
201 echo "$type $oid" >expect &&
202 echo "info $oid" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual &&
203 test_cmp expect actual
206 test_expect_success '--batch-check with %(rest)' '
207 echo "$type this is some extra content" >expect &&
208 echo "$oid this is some extra content" |
209 git cat-file --batch-check="%(objecttype) %(rest)" >actual &&
210 test_cmp expect actual
213 test -z "$content" ||
214 test_expect_success "--batch without type ($type)" '
216 echo "$size" &&
217 echo "$content"
218 } >expect &&
219 echo $oid | git cat-file --batch="%(objectsize)" >actual &&
220 test_cmp expect actual
223 test -z "$content" ||
224 test_expect_success "--batch without size ($type)" '
226 echo "$type" &&
227 echo "$content"
228 } >expect &&
229 echo $oid | git cat-file --batch="%(objecttype)" >actual &&
230 test_cmp expect actual
234 hello_content="Hello World"
235 hello_size=$(strlen "$hello_content")
236 hello_oid=$(echo_without_newline "$hello_content" | git hash-object --stdin)
238 test_expect_success "setup" '
239 git config core.repositoryformatversion 1 &&
240 git config extensions.objectformat $test_hash_algo &&
241 git config extensions.compatobjectformat $test_compat_hash_algo &&
242 echo_without_newline "$hello_content" > hello &&
243 git update-index --add hello
246 run_blob_tests () {
247 oid=$1
249 run_tests 'blob' $oid $hello_size "$hello_content" "$hello_content"
251 test_expect_success '--batch-command --buffer with flush for blob info' '
252 echo "$oid blob $hello_size" >expect &&
253 test_write_lines "info $oid" "flush" |
254 GIT_TEST_CAT_FILE_NO_FLUSH_ON_EXIT=1 \
255 git cat-file --batch-command --buffer >actual &&
256 test_cmp expect actual
259 test_expect_success '--batch-command --buffer without flush for blob info' '
260 touch output &&
261 test_write_lines "info $oid" |
262 GIT_TEST_CAT_FILE_NO_FLUSH_ON_EXIT=1 \
263 git cat-file --batch-command --buffer >>output &&
264 test_must_be_empty output
268 hello_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $hello_oid)
269 run_blob_tests $hello_oid
270 run_blob_tests $hello_compat_oid
272 test_expect_success '--batch-check without %(rest) considers whole line' '
273 echo "$hello_oid blob $hello_size" >expect &&
274 git update-index --add --cacheinfo 100644 $hello_oid "white space" &&
275 test_when_finished "git update-index --remove \"white space\"" &&
276 echo ":white space" | git cat-file --batch-check >actual &&
277 test_cmp expect actual
280 tree_oid=$(git write-tree)
281 tree_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tree_oid)
282 tree_size=$(($(test_oid rawsz) + 13))
283 tree_compat_size=$(($(test_oid --hash=compat rawsz) + 13))
284 tree_pretty_content="100644 blob $hello_oid hello${LF}"
285 tree_compat_pretty_content="100644 blob $hello_compat_oid hello${LF}"
287 run_tests 'tree' $tree_oid $tree_size "" "$tree_pretty_content"
288 run_tests 'tree' $tree_compat_oid $tree_compat_size "" "$tree_compat_pretty_content"
290 commit_message="Initial commit"
291 commit_oid=$(echo_without_newline "$commit_message" | git commit-tree $tree_oid)
292 commit_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $commit_oid)
293 commit_size=$(($(test_oid hexsz) + 137))
294 commit_compat_size=$(($(test_oid --hash=compat hexsz) + 137))
295 commit_content="tree $tree_oid
296 author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE
297 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
299 $commit_message"
301 commit_compat_content="tree $tree_compat_oid
302 author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE
303 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
305 $commit_message"
307 run_tests 'commit' $commit_oid $commit_size "$commit_content" "$commit_content"
308 run_tests 'commit' $commit_compat_oid $commit_compat_size "$commit_compat_content" "$commit_compat_content"
310 tag_header_without_oid="type blob
311 tag hellotag
312 tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
313 tag_header_without_timestamp="object $hello_oid
314 $tag_header_without_oid"
315 tag_compat_header_without_timestamp="object $hello_compat_oid
316 $tag_header_without_oid"
317 tag_description="This is a tag"
318 tag_content="$tag_header_without_timestamp 0 +0000
320 $tag_description"
321 tag_compat_content="$tag_compat_header_without_timestamp 0 +0000
323 $tag_description"
325 tag_oid=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
326 tag_size=$(strlen "$tag_content")
328 tag_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tag_oid)
329 tag_compat_size=$(strlen "$tag_compat_content")
331 run_tests 'tag' $tag_oid $tag_size "$tag_content" "$tag_content"
332 run_tests 'tag' $tag_compat_oid $tag_compat_size "$tag_compat_content" "$tag_compat_content"
334 test_expect_success "Reach a blob from a tag pointing to it" '
335 echo_without_newline "$hello_content" >expect &&
336 git cat-file blob $tag_oid >actual &&
337 test_cmp expect actual
340 for oid in $hello_oid $hello_compat_oid
342 for batch in batch batch-check batch-command
344 for opt in t s e p
346 test_expect_success "Passing -$opt with --$batch fails" '
347 test_must_fail git cat-file --$batch -$opt $oid
350 test_expect_success "Passing --$batch with -$opt fails" '
351 test_must_fail git cat-file -$opt --$batch $oid
353 done
355 test_expect_success "Passing <type> with --$batch fails" '
356 test_must_fail git cat-file --$batch blob $oid
359 test_expect_success "Passing --$batch with <type> fails" '
360 test_must_fail git cat-file blob --$batch $oid
363 test_expect_success "Passing oid with --$batch fails" '
364 test_must_fail git cat-file --$batch $oid
366 done
367 done
369 for oid in $hello_oid $hello_compat_oid
371 for opt in t s e p
373 test_expect_success "Passing -$opt with --follow-symlinks fails" '
374 test_must_fail git cat-file --follow-symlinks -$opt $oid
376 done
377 done
379 test_expect_success "--batch-check for a non-existent named object" '
380 cat >expect <<-EOF &&
381 foobar42 missing
382 foobar84 missing
385 printf "foobar42\nfoobar84" >in &&
386 git cat-file --batch-check <in >actual &&
387 test_cmp expect actual
390 test_expect_success "--batch-check for a non-existent hash" '
391 cat >expect <<-EOF &&
392 0000000000000000000000000000000000000042 missing
393 0000000000000000000000000000000000000084 missing
396 printf "0000000000000000000000000000000000000042\n0000000000000000000000000000000000000084" >in &&
397 git cat-file --batch-check <in >actual &&
398 test_cmp expect actual
401 test_expect_success "--batch for an existent and a non-existent hash" '
402 cat >expect <<-EOF &&
403 $tag_oid tag $tag_size
404 $tag_content
405 0000000000000000000000000000000000000000 missing
408 printf "$tag_oid\n0000000000000000000000000000000000000000" >in &&
409 git cat-file --batch <in >actual &&
410 test_cmp expect actual
413 test_expect_success "--batch-check for an empty line" '
414 cat >expect <<-EOF &&
415 missing
418 echo >in &&
419 git cat-file --batch-check <in >actual &&
420 test_cmp expect actual
423 test_expect_success 'empty --batch-check notices missing object' '
424 echo "$ZERO_OID missing" >expect &&
425 echo "$ZERO_OID" | git cat-file --batch-check="" >actual &&
426 test_cmp expect actual
429 batch_tests () {
430 boid=$1
431 loid=$2
432 lsize=$3
433 coid=$4
434 csize=$5
435 ccontent=$6
436 toid=$7
437 tsize=$8
438 tcontent=$9
440 batch_input="$boid
441 $coid
442 $toid
443 deadbeef
447 printf "%s\0" \
448 "$boid blob $hello_size" \
449 "$hello_content" \
450 "$coid commit $csize" \
451 "$ccontent" \
452 "$toid tag $tsize" \
453 "$tcontent" \
454 "deadbeef missing" \
455 " missing" >batch_output
457 test_expect_success '--batch with multiple oids gives correct format' '
458 tr "\0" "\n" <batch_output >expect &&
459 echo_without_newline "$batch_input" >in &&
460 git cat-file --batch <in >actual &&
461 test_cmp expect actual
464 test_expect_success '--batch, -z with multiple oids gives correct format' '
465 echo_without_newline_nul "$batch_input" >in &&
466 tr "\0" "\n" <batch_output >expect &&
467 git cat-file --batch -z <in >actual &&
468 test_cmp expect actual
471 test_expect_success '--batch, -Z with multiple oids gives correct format' '
472 echo_without_newline_nul "$batch_input" >in &&
473 git cat-file --batch -Z <in >actual &&
474 test_cmp batch_output actual
477 batch_check_input="$boid
478 $loid
479 $coid
480 $toid
481 deadbeef
485 printf "%s\0" \
486 "$boid blob $hello_size" \
487 "$loid tree $lsize" \
488 "$coid commit $csize" \
489 "$toid tag $tsize" \
490 "deadbeef missing" \
491 " missing" >batch_check_output
493 test_expect_success "--batch-check with multiple oids gives correct format" '
494 tr "\0" "\n" <batch_check_output >expect &&
495 echo_without_newline "$batch_check_input" >in &&
496 git cat-file --batch-check <in >actual &&
497 test_cmp expect actual
500 test_expect_success "--batch-check, -z with multiple oids gives correct format" '
501 tr "\0" "\n" <batch_check_output >expect &&
502 echo_without_newline_nul "$batch_check_input" >in &&
503 git cat-file --batch-check -z <in >actual &&
504 test_cmp expect actual
507 test_expect_success "--batch-check, -Z with multiple oids gives correct format" '
508 echo_without_newline_nul "$batch_check_input" >in &&
509 git cat-file --batch-check -Z <in >actual &&
510 test_cmp batch_check_output actual
513 batch_command_multiple_info="info $boid
514 info $loid
515 info $coid
516 info $toid
517 info deadbeef"
519 test_expect_success '--batch-command with multiple info calls gives correct format' '
520 cat >expect <<-EOF &&
521 $boid blob $hello_size
522 $loid tree $lsize
523 $coid commit $csize
524 $toid tag $tsize
525 deadbeef missing
528 echo "$batch_command_multiple_info" >in &&
529 git cat-file --batch-command --buffer <in >actual &&
531 test_cmp expect actual &&
533 echo "$batch_command_multiple_info" | tr "\n" "\0" >in &&
534 git cat-file --batch-command --buffer -z <in >actual &&
536 test_cmp expect actual &&
538 echo "$batch_command_multiple_info" | tr "\n" "\0" >in &&
539 tr "\n" "\0" <expect >expect_nul &&
540 git cat-file --batch-command --buffer -Z <in >actual &&
542 test_cmp expect_nul actual
545 batch_command_multiple_contents="contents $boid
546 contents $coid
547 contents $toid
548 contents deadbeef
549 flush"
551 test_expect_success '--batch-command with multiple command calls gives correct format' '
552 printf "%s\0" \
553 "$boid blob $hello_size" \
554 "$hello_content" \
555 "$coid commit $csize" \
556 "$ccontent" \
557 "$toid tag $tsize" \
558 "$tcontent" \
559 "deadbeef missing" >expect_nul &&
560 tr "\0" "\n" <expect_nul >expect &&
562 echo "$batch_command_multiple_contents" >in &&
563 git cat-file --batch-command --buffer <in >actual &&
565 test_cmp expect actual &&
567 echo "$batch_command_multiple_contents" | tr "\n" "\0" >in &&
568 git cat-file --batch-command --buffer -z <in >actual &&
570 test_cmp expect actual &&
572 echo "$batch_command_multiple_contents" | tr "\n" "\0" >in &&
573 git cat-file --batch-command --buffer -Z <in >actual &&
575 test_cmp expect_nul actual
580 batch_tests $hello_oid $tree_oid $tree_size $commit_oid $commit_size "$commit_content" $tag_oid $tag_size "$tag_content"
581 batch_tests $hello_compat_oid $tree_compat_oid $tree_compat_size $commit_compat_oid $commit_compat_size "$commit_compat_content" $tag_compat_oid $tag_compat_size "$tag_compat_content"
584 test_expect_success FUNNYNAMES 'setup with newline in input' '
585 touch -- "newline${LF}embedded" &&
586 git add -- "newline${LF}embedded" &&
587 git commit -m "file with newline embedded" &&
588 test_tick &&
590 printf "HEAD:newline${LF}embedded" >in
593 test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' '
594 git cat-file --batch-check -z <in >actual &&
595 echo "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect &&
596 test_cmp expect actual
599 test_expect_success FUNNYNAMES '--batch-check, -Z with newline in input' '
600 git cat-file --batch-check -Z <in >actual &&
601 printf "%s\0" "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect &&
602 test_cmp expect actual
605 test_expect_success 'setup blobs which are likely to delta' '
606 test-tool genrandom foo 10240 >foo &&
607 { cat foo && echo plus; } >foo-plus &&
608 git add foo foo-plus &&
609 git commit -m foo &&
610 cat >blobs <<-\EOF
611 HEAD:foo
612 HEAD:foo-plus
616 test_expect_success 'confirm that neither loose blob is a delta' '
617 cat >expect <<-EOF &&
618 $ZERO_OID
619 $ZERO_OID
621 git cat-file --batch-check="%(deltabase)" <blobs >actual &&
622 test_cmp expect actual
625 # To avoid relying too much on the current delta heuristics,
626 # we will check only that one of the two objects is a delta
627 # against the other, but not the order. We can do so by just
628 # asking for the base of both, and checking whether either
629 # oid appears in the output.
630 test_expect_success '%(deltabase) reports packed delta bases' '
631 git repack -ad &&
632 git cat-file --batch-check="%(deltabase)" <blobs >actual &&
634 grep "$(git rev-parse HEAD:foo)" actual ||
635 grep "$(git rev-parse HEAD:foo-plus)" actual
639 test_expect_success 'setup bogus data' '
640 bogus_short_type="bogus" &&
641 bogus_short_content="bogus" &&
642 bogus_short_size=$(strlen "$bogus_short_content") &&
643 bogus_short_oid=$(echo_without_newline "$bogus_short_content" | git hash-object -t $bogus_short_type --literally -w --stdin) &&
645 bogus_long_type="abcdefghijklmnopqrstuvwxyz1234679" &&
646 bogus_long_content="bogus" &&
647 bogus_long_size=$(strlen "$bogus_long_content") &&
648 bogus_long_oid=$(echo_without_newline "$bogus_long_content" | git hash-object -t $bogus_long_type --literally -w --stdin)
651 for arg1 in '' --allow-unknown-type
653 for arg2 in -s -t -p
655 if test "$arg1" = "--allow-unknown-type" && test "$arg2" = "-p"
656 then
657 continue
661 test_expect_success "cat-file $arg1 $arg2 error on bogus short OID" '
662 cat >expect <<-\EOF &&
663 fatal: invalid object type
666 if test "$arg1" = "--allow-unknown-type"
667 then
668 git cat-file $arg1 $arg2 $bogus_short_oid
669 else
670 test_must_fail git cat-file $arg1 $arg2 $bogus_short_oid >out 2>actual &&
671 test_must_be_empty out &&
672 test_cmp expect actual
676 test_expect_success "cat-file $arg1 $arg2 error on bogus full OID" '
677 if test "$arg2" = "-p"
678 then
679 cat >expect <<-EOF
680 error: header for $bogus_long_oid too long, exceeds 32 bytes
681 fatal: Not a valid object name $bogus_long_oid
683 else
684 cat >expect <<-EOF
685 error: header for $bogus_long_oid too long, exceeds 32 bytes
686 fatal: git cat-file: could not get object info
688 fi &&
690 if test "$arg1" = "--allow-unknown-type"
691 then
692 git cat-file $arg1 $arg2 $bogus_short_oid
693 else
694 test_must_fail git cat-file $arg1 $arg2 $bogus_long_oid >out 2>actual &&
695 test_must_be_empty out &&
696 test_cmp expect actual
700 test_expect_success "cat-file $arg1 $arg2 error on missing short OID" '
701 cat >expect.err <<-EOF &&
702 fatal: Not a valid object name $(test_oid deadbeef_short)
704 test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual &&
705 test_must_be_empty out &&
706 test_cmp expect.err err.actual
709 test_expect_success "cat-file $arg1 $arg2 error on missing full OID" '
710 if test "$arg2" = "-p"
711 then
712 cat >expect.err <<-EOF
713 fatal: Not a valid object name $(test_oid deadbeef)
715 else
716 cat >expect.err <<-\EOF
717 fatal: git cat-file: could not get object info
719 fi &&
720 test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef) >out 2>err.actual &&
721 test_must_be_empty out &&
722 test_cmp expect.err err.actual
724 done
725 done
727 test_expect_success '-e is OK with a broken object without --allow-unknown-type' '
728 git cat-file -e $bogus_short_oid
731 test_expect_success '-e can not be combined with --allow-unknown-type' '
732 test_expect_code 128 git cat-file -e --allow-unknown-type $bogus_short_oid
735 test_expect_success '-p cannot print a broken object even with --allow-unknown-type' '
736 test_must_fail git cat-file -p $bogus_short_oid &&
737 test_expect_code 128 git cat-file -p --allow-unknown-type $bogus_short_oid
740 test_expect_success '<type> <hash> does not work with objects of broken types' '
741 cat >err.expect <<-\EOF &&
742 fatal: invalid object type "bogus"
744 test_must_fail git cat-file $bogus_short_type $bogus_short_oid 2>err.actual &&
745 test_cmp err.expect err.actual
748 test_expect_success 'broken types combined with --batch and --batch-check' '
749 echo $bogus_short_oid >bogus-oid &&
751 cat >err.expect <<-\EOF &&
752 fatal: invalid object type
755 test_must_fail git cat-file --batch <bogus-oid 2>err.actual &&
756 test_cmp err.expect err.actual &&
758 test_must_fail git cat-file --batch-check <bogus-oid 2>err.actual &&
759 test_cmp err.expect err.actual
762 test_expect_success 'the --batch and --batch-check options do not combine with --allow-unknown-type' '
763 test_expect_code 128 git cat-file --batch --allow-unknown-type <bogus-oid &&
764 test_expect_code 128 git cat-file --batch-check --allow-unknown-type <bogus-oid
767 test_expect_success 'the --allow-unknown-type option does not consider replacement refs' '
768 cat >expect <<-EOF &&
769 $bogus_short_type
771 git cat-file -t --allow-unknown-type $bogus_short_oid >actual &&
772 test_cmp expect actual &&
774 # Create it manually, as "git replace" will die on bogus
775 # types.
776 head=$(git rev-parse --verify HEAD) &&
777 test_when_finished "test-tool ref-store main delete-refs 0 msg refs/replace/$bogus_short_oid" &&
778 test-tool ref-store main update-ref msg "refs/replace/$bogus_short_oid" $head $ZERO_OID REF_SKIP_OID_VERIFICATION &&
780 cat >expect <<-EOF &&
781 commit
783 git cat-file -t --allow-unknown-type $bogus_short_oid >actual &&
784 test_cmp expect actual
787 test_expect_success "Type of broken object is correct" '
788 echo $bogus_short_type >expect &&
789 git cat-file -t --allow-unknown-type $bogus_short_oid >actual &&
790 test_cmp expect actual
793 test_expect_success "Size of broken object is correct" '
794 echo $bogus_short_size >expect &&
795 git cat-file -s --allow-unknown-type $bogus_short_oid >actual &&
796 test_cmp expect actual
799 test_expect_success 'clean up broken object' '
800 rm .git/objects/$(test_oid_to_path $bogus_short_oid)
803 test_expect_success "Type of broken object is correct when type is large" '
804 echo $bogus_long_type >expect &&
805 git cat-file -t --allow-unknown-type $bogus_long_oid >actual &&
806 test_cmp expect actual
809 test_expect_success "Size of large broken object is correct when type is large" '
810 echo $bogus_long_size >expect &&
811 git cat-file -s --allow-unknown-type $bogus_long_oid >actual &&
812 test_cmp expect actual
815 test_expect_success 'clean up broken object' '
816 rm .git/objects/$(test_oid_to_path $bogus_long_oid)
819 test_expect_success 'cat-file -t and -s on corrupt loose object' '
820 git init --bare corrupt-loose.git &&
822 cd corrupt-loose.git &&
824 # Setup and create the empty blob and its path
825 empty_path=$(git rev-parse --git-path objects/$(test_oid_to_path "$EMPTY_BLOB")) &&
826 empty_blob=$(git hash-object -w --stdin </dev/null) &&
828 # Create another blob and its path
829 echo other >other.blob &&
830 other_blob=$(git hash-object -w --stdin <other.blob) &&
831 other_path=$(git rev-parse --git-path objects/$(test_oid_to_path "$other_blob")) &&
833 # Before the swap the size is 0
834 cat >out.expect <<-EOF &&
837 git cat-file -s "$EMPTY_BLOB" >out.actual 2>err.actual &&
838 test_must_be_empty err.actual &&
839 test_cmp out.expect out.actual &&
841 # Swap the two to corrupt the repository
842 mv -f "$other_path" "$empty_path" &&
843 test_must_fail git fsck 2>err.fsck &&
844 grep "hash-path mismatch" err.fsck &&
846 # confirm that cat-file is reading the new swapped-in
847 # blob...
848 cat >out.expect <<-EOF &&
849 blob
851 git cat-file -t "$EMPTY_BLOB" >out.actual 2>err.actual &&
852 test_must_be_empty err.actual &&
853 test_cmp out.expect out.actual &&
855 # ... since it has a different size now.
856 cat >out.expect <<-EOF &&
859 git cat-file -s "$EMPTY_BLOB" >out.actual 2>err.actual &&
860 test_must_be_empty err.actual &&
861 test_cmp out.expect out.actual &&
863 # So far "cat-file" has been happy to spew the found
864 # content out as-is. Try to make it zlib-invalid.
865 mv -f other.blob "$empty_path" &&
866 test_must_fail git fsck 2>err.fsck &&
867 cat >expect <<-EOF &&
868 error: inflate: data stream error (incorrect header check)
869 error: unable to unpack header of ./$empty_path
870 error: $empty_blob: object corrupt or missing: ./$empty_path
872 grep "^error: " err.fsck >actual &&
873 test_cmp expect actual
877 # Tests for git cat-file --follow-symlinks
878 test_expect_success 'prep for symlink tests' '
879 echo_without_newline "$hello_content" >morx &&
880 test_ln_s_add morx same-dir-link &&
881 test_ln_s_add dir link-to-dir &&
882 test_ln_s_add ../fleem out-of-repo-link &&
883 test_ln_s_add .. out-of-repo-link-dir &&
884 test_ln_s_add same-dir-link link-to-link &&
885 test_ln_s_add nope broken-same-dir-link &&
886 mkdir dir &&
887 test_ln_s_add ../morx dir/parent-dir-link &&
888 test_ln_s_add .. dir/link-dir &&
889 test_ln_s_add ../../escape dir/out-of-repo-link &&
890 test_ln_s_add ../.. dir/out-of-repo-link-dir &&
891 test_ln_s_add nope dir/broken-link-in-dir &&
892 mkdir dir/subdir &&
893 test_ln_s_add ../../morx dir/subdir/grandparent-dir-link &&
894 test_ln_s_add ../../../great-escape dir/subdir/out-of-repo-link &&
895 test_ln_s_add ../../.. dir/subdir/out-of-repo-link-dir &&
896 test_ln_s_add ../../../ dir/subdir/out-of-repo-link-dir-trailing &&
897 test_ln_s_add ../parent-dir-link dir/subdir/parent-dir-link-to-link &&
898 echo_without_newline "$hello_content" >dir/subdir/ind2 &&
899 echo_without_newline "$hello_content" >dir/ind1 &&
900 test_ln_s_add dir dirlink &&
901 test_ln_s_add dir/subdir subdirlink &&
902 test_ln_s_add subdir/ind2 dir/link-to-child &&
903 test_ln_s_add dir/link-to-child link-to-down-link &&
904 test_ln_s_add dir/.. up-down &&
905 test_ln_s_add dir/../ up-down-trailing &&
906 test_ln_s_add dir/../morx up-down-file &&
907 test_ln_s_add dir/../../morx up-up-down-file &&
908 test_ln_s_add subdirlink/../../morx up-two-down-file &&
909 test_ln_s_add loop1 loop2 &&
910 test_ln_s_add loop2 loop1 &&
911 git add morx dir/subdir/ind2 dir/ind1 &&
912 git commit -am "test" &&
913 echo $hello_oid blob $hello_size >found
916 test_expect_success 'git cat-file --batch-check --follow-symlinks works for non-links' '
917 echo HEAD:morx | git cat-file --batch-check --follow-symlinks >actual &&
918 test_cmp found actual &&
919 echo HEAD:nope missing >expect &&
920 echo HEAD:nope | git cat-file --batch-check --follow-symlinks >actual &&
921 test_cmp expect actual
924 test_expect_success 'git cat-file --batch-check --follow-symlinks works for in-repo, same-dir links' '
925 echo HEAD:same-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
926 test_cmp found actual
929 test_expect_success 'git cat-file --batch-check --follow-symlinks works for in-repo, links to dirs' '
930 echo HEAD:link-to-dir/ind1 | git cat-file --batch-check --follow-symlinks >actual &&
931 test_cmp found actual
935 test_expect_success 'git cat-file --batch-check --follow-symlinks works for broken in-repo, same-dir links' '
936 echo dangling 25 >expect &&
937 echo HEAD:broken-same-dir-link >>expect &&
938 echo HEAD:broken-same-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
939 test_cmp expect actual
942 test_expect_success 'git cat-file --batch-check --follow-symlinks -Z works for broken in-repo, same-dir links' '
943 printf "HEAD:broken-same-dir-link\0" >in &&
944 printf "dangling 25\0HEAD:broken-same-dir-link\0" >expect &&
945 git cat-file --batch-check --follow-symlinks -Z <in >actual &&
946 test_cmp expect actual
949 test_expect_success 'git cat-file --batch-check --follow-symlinks works for same-dir links-to-links' '
950 echo HEAD:link-to-link | git cat-file --batch-check --follow-symlinks >actual &&
951 test_cmp found actual
954 test_expect_success 'git cat-file --batch-check --follow-symlinks works for parent-dir links' '
955 echo HEAD:dir/parent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
956 test_cmp found actual &&
957 echo notdir 29 >expect &&
958 echo HEAD:dir/parent-dir-link/nope >>expect &&
959 echo HEAD:dir/parent-dir-link/nope | git cat-file --batch-check --follow-symlinks >actual &&
960 test_cmp expect actual
963 test_expect_success 'git cat-file --batch-check --follow-symlinks -Z works for parent-dir links' '
964 echo HEAD:dir/parent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
965 test_cmp found actual &&
966 printf "notdir 29\0HEAD:dir/parent-dir-link/nope\0" >expect &&
967 printf "HEAD:dir/parent-dir-link/nope\0" >in &&
968 git cat-file --batch-check --follow-symlinks -Z <in >actual &&
969 test_cmp expect actual
972 test_expect_success 'git cat-file --batch-check --follow-symlinks works for .. links' '
973 echo dangling 22 >expect &&
974 echo HEAD:dir/link-dir/nope >>expect &&
975 echo HEAD:dir/link-dir/nope | git cat-file --batch-check --follow-symlinks >actual &&
976 test_cmp expect actual &&
977 echo HEAD:dir/link-dir/morx | git cat-file --batch-check --follow-symlinks >actual &&
978 test_cmp found actual &&
979 echo dangling 27 >expect &&
980 echo HEAD:dir/broken-link-in-dir >>expect &&
981 echo HEAD:dir/broken-link-in-dir | git cat-file --batch-check --follow-symlinks >actual &&
982 test_cmp expect actual
985 test_expect_success 'git cat-file --batch-check --follow-symlinks works for ../.. links' '
986 echo notdir 41 >expect &&
987 echo HEAD:dir/subdir/grandparent-dir-link/nope >>expect &&
988 echo HEAD:dir/subdir/grandparent-dir-link/nope | git cat-file --batch-check --follow-symlinks >actual &&
989 test_cmp expect actual &&
990 echo HEAD:dir/subdir/grandparent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
991 test_cmp found actual &&
992 echo HEAD:dir/subdir/parent-dir-link-to-link | git cat-file --batch-check --follow-symlinks >actual &&
993 test_cmp found actual
996 test_expect_success 'git cat-file --batch-check --follow-symlinks works for dir/ links' '
997 echo dangling 17 >expect &&
998 echo HEAD:dirlink/morx >>expect &&
999 echo HEAD:dirlink/morx | git cat-file --batch-check --follow-symlinks >actual &&
1000 test_cmp expect actual &&
1001 echo $hello_oid blob $hello_size >expect &&
1002 echo HEAD:dirlink/ind1 | git cat-file --batch-check --follow-symlinks >actual &&
1003 test_cmp expect actual
1006 test_expect_success 'git cat-file --batch-check --follow-symlinks works for dir/subdir links' '
1007 echo dangling 20 >expect &&
1008 echo HEAD:subdirlink/morx >>expect &&
1009 echo HEAD:subdirlink/morx | git cat-file --batch-check --follow-symlinks >actual &&
1010 test_cmp expect actual &&
1011 echo HEAD:subdirlink/ind2 | git cat-file --batch-check --follow-symlinks >actual &&
1012 test_cmp found actual
1015 test_expect_success 'git cat-file --batch-check --follow-symlinks works for dir ->subdir links' '
1016 echo notdir 27 >expect &&
1017 echo HEAD:dir/link-to-child/morx >>expect &&
1018 echo HEAD:dir/link-to-child/morx | git cat-file --batch-check --follow-symlinks >actual &&
1019 test_cmp expect actual &&
1020 echo HEAD:dir/link-to-child | git cat-file --batch-check --follow-symlinks >actual &&
1021 test_cmp found actual &&
1022 echo HEAD:link-to-down-link | git cat-file --batch-check --follow-symlinks >actual &&
1023 test_cmp found actual
1026 test_expect_success 'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks' '
1027 echo symlink 8 >expect &&
1028 echo ../fleem >>expect &&
1029 echo HEAD:out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&
1030 test_cmp expect actual &&
1031 echo symlink 2 >expect &&
1032 echo .. >>expect &&
1033 echo HEAD:out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&
1034 test_cmp expect actual
1037 test_expect_success 'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks in dirs' '
1038 echo symlink 9 >expect &&
1039 echo ../escape >>expect &&
1040 echo HEAD:dir/out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&
1041 test_cmp expect actual &&
1042 echo symlink 2 >expect &&
1043 echo .. >>expect &&
1044 echo HEAD:dir/out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&
1045 test_cmp expect actual
1048 test_expect_success 'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks in subdirs' '
1049 echo symlink 15 >expect &&
1050 echo ../great-escape >>expect &&
1051 echo HEAD:dir/subdir/out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&
1052 test_cmp expect actual &&
1053 echo symlink 2 >expect &&
1054 echo .. >>expect &&
1055 echo HEAD:dir/subdir/out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&
1056 test_cmp expect actual &&
1057 echo symlink 3 >expect &&
1058 echo ../ >>expect &&
1059 echo HEAD:dir/subdir/out-of-repo-link-dir-trailing | git cat-file --batch-check --follow-symlinks >actual &&
1060 test_cmp expect actual
1063 test_expect_success 'git cat-file --batch-check --follow-symlinks works for symlinks with internal ..' '
1064 echo HEAD: | git cat-file --batch-check >expect &&
1065 echo HEAD:up-down | git cat-file --batch-check --follow-symlinks >actual &&
1066 test_cmp expect actual &&
1067 echo HEAD:up-down-trailing | git cat-file --batch-check --follow-symlinks >actual &&
1068 test_cmp expect actual &&
1069 echo HEAD:up-down-file | git cat-file --batch-check --follow-symlinks >actual &&
1070 test_cmp found actual &&
1071 echo symlink 7 >expect &&
1072 echo ../morx >>expect &&
1073 echo HEAD:up-up-down-file | git cat-file --batch-check --follow-symlinks >actual &&
1074 test_cmp expect actual &&
1075 echo HEAD:up-two-down-file | git cat-file --batch-check --follow-symlinks >actual &&
1076 test_cmp found actual
1079 test_expect_success 'git cat-file --batch-check --follow-symlink breaks loops' '
1080 echo loop 10 >expect &&
1081 echo HEAD:loop1 >>expect &&
1082 echo HEAD:loop1 | git cat-file --batch-check --follow-symlinks >actual &&
1083 test_cmp expect actual
1086 test_expect_success 'git cat-file --batch-check --follow-symlink -Z breaks loops' '
1087 printf "loop 10\0HEAD:loop1\0" >expect &&
1088 printf "HEAD:loop1\0" >in &&
1089 git cat-file --batch-check --follow-symlinks -Z <in >actual &&
1090 test_cmp expect actual
1093 test_expect_success 'git cat-file --batch --follow-symlink returns correct sha and mode' '
1094 echo HEAD:morx | git cat-file --batch >expect &&
1095 echo HEAD:morx | git cat-file --batch --follow-symlinks >actual &&
1096 test_cmp expect actual
1099 test_expect_success 'cat-file --batch-all-objects shows all objects' '
1100 # make new repos so we know the full set of objects; we will
1101 # also make sure that there are some packed and some loose
1102 # objects, some referenced and some not, some duplicates, and that
1103 # there are some available only via alternates.
1104 git init all-one &&
1106 cd all-one &&
1107 echo content >file &&
1108 git add file &&
1109 git commit -qm base &&
1110 git rev-parse HEAD HEAD^{tree} HEAD:file &&
1111 git repack -ad &&
1112 echo not-cloned | git hash-object -w --stdin
1113 ) >expect.unsorted &&
1114 git clone -s all-one all-two &&
1116 cd all-two &&
1117 echo local-unref | git hash-object -w --stdin
1118 ) >>expect.unsorted &&
1119 git -C all-two rev-parse HEAD:file |
1120 git -C all-two pack-objects .git/objects/pack/pack &&
1121 sort <expect.unsorted >expect &&
1122 git -C all-two cat-file --batch-all-objects \
1123 --batch-check="%(objectname)" >actual &&
1124 test_cmp expect actual
1127 # The only user-visible difference is that the objects are no longer sorted,
1128 # and the resulting sort order is undefined. So we can only check that it
1129 # produces the same objects as the ordered case, but that at least exercises
1130 # the code.
1131 test_expect_success 'cat-file --unordered works' '
1132 git -C all-two cat-file --batch-all-objects --unordered \
1133 --batch-check="%(objectname)" >actual.unsorted &&
1134 sort <actual.unsorted >actual &&
1135 test_cmp expect actual
1138 test_expect_success 'set up object list for --batch-all-objects tests' '
1139 git -C all-two cat-file --batch-all-objects --batch-check="%(objectname)" >objects
1142 test_expect_success 'cat-file --batch="%(objectname)" with --batch-all-objects will work' '
1143 git -C all-two cat-file --batch="%(objectname)" <objects >expect &&
1144 git -C all-two cat-file --batch-all-objects --batch="%(objectname)" >actual &&
1145 cmp expect actual
1148 test_expect_success 'cat-file --batch="%(rest)" with --batch-all-objects will work' '
1149 git -C all-two cat-file --batch="%(rest)" <objects >expect &&
1150 git -C all-two cat-file --batch-all-objects --batch="%(rest)" >actual &&
1151 cmp expect actual
1154 test_expect_success 'cat-file --batch="batman" with --batch-all-objects will work' '
1155 git -C all-two cat-file --batch="batman" <objects >expect &&
1156 git -C all-two cat-file --batch-all-objects --batch="batman" >actual &&
1157 cmp expect actual
1160 test_expect_success 'cat-file %(objectsize:disk) with --batch-all-objects' '
1161 # our state has both loose and packed objects,
1162 # so find both for our expected output
1164 find .git/objects/?? -type f |
1165 awk -F/ "{ print \$0, \$3\$4 }" |
1166 while read path oid
1168 size=$(test_file_size "$path") &&
1169 echo "$oid $size" ||
1170 return 1
1171 done &&
1172 rawsz=$(test_oid rawsz) &&
1173 find .git/objects/pack -name "*.idx" |
1174 while read idx
1176 git show-index <"$idx" >idx.raw &&
1177 sort -nr <idx.raw >idx.sorted &&
1178 packsz=$(test_file_size "${idx%.idx}.pack") &&
1179 end=$((packsz - rawsz)) &&
1180 while read start oid rest
1182 size=$((end - start)) &&
1183 end=$start &&
1184 echo "$oid $size" ||
1185 return 1
1186 done <idx.sorted ||
1187 return 1
1188 done
1189 } >expect.raw &&
1190 sort <expect.raw >expect &&
1191 git cat-file --batch-all-objects \
1192 --batch-check="%(objectname) %(objectsize:disk)" >actual &&
1193 test_cmp expect actual
1196 test_expect_success 'set up replacement object' '
1197 orig=$(git rev-parse HEAD) &&
1198 git cat-file commit $orig >orig &&
1200 cat orig &&
1201 echo extra
1202 } >fake &&
1203 fake=$(git hash-object -t commit -w fake) &&
1204 orig_size=$(git cat-file -s $orig) &&
1205 fake_size=$(git cat-file -s $fake) &&
1206 git replace $orig $fake
1209 test_expect_success 'cat-file --batch respects replace objects' '
1210 git cat-file --batch >actual <<-EOF &&
1211 $orig
1214 echo "$orig commit $fake_size" &&
1215 cat fake &&
1216 echo
1217 } >expect &&
1218 test_cmp expect actual
1221 test_expect_success 'cat-file --batch-check respects replace objects' '
1222 git cat-file --batch-check >actual <<-EOF &&
1223 $orig
1225 echo "$orig commit $fake_size" >expect &&
1226 test_cmp expect actual
1229 # Pull the entry for object with oid "$1" out of the output of
1230 # "cat-file --batch", including its object content (which requires
1231 # parsing and reading a set amount of bytes, hence perl).
1232 extract_batch_output () {
1233 perl -ne '
1234 BEGIN { $oid = shift }
1235 if (/^$oid \S+ (\d+)$/) {
1236 print;
1237 read STDIN, my $buf, $1;
1238 print $buf;
1239 print "\n";
1241 ' "$@"
1244 test_expect_success 'cat-file --batch-all-objects --batch ignores replace' '
1245 git cat-file --batch-all-objects --batch >actual.raw &&
1246 extract_batch_output $orig <actual.raw >actual &&
1248 echo "$orig commit $orig_size" &&
1249 cat orig &&
1250 echo
1251 } >expect &&
1252 test_cmp expect actual
1255 test_expect_success 'cat-file --batch-all-objects --batch-check ignores replace' '
1256 git cat-file --batch-all-objects --batch-check >actual.raw &&
1257 grep ^$orig actual.raw >actual &&
1258 echo "$orig commit $orig_size" >expect &&
1259 test_cmp expect actual
1261 test_expect_success 'batch-command empty command' '
1262 echo "" >cmd &&
1263 test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
1264 grep "^fatal:.*empty command in input.*" err
1267 test_expect_success 'batch-command whitespace before command' '
1268 echo " info deadbeef" >cmd &&
1269 test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
1270 grep "^fatal:.*whitespace before command.*" err
1273 test_expect_success 'batch-command unknown command' '
1274 echo unknown_command >cmd &&
1275 test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
1276 grep "^fatal:.*unknown command.*" err
1279 test_expect_success 'batch-command missing arguments' '
1280 echo "info" >cmd &&
1281 test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
1282 grep "^fatal:.*info requires arguments.*" err
1285 test_expect_success 'batch-command flush with arguments' '
1286 echo "flush arg" >cmd &&
1287 test_expect_code 128 git cat-file --batch-command --buffer <cmd 2>err &&
1288 grep "^fatal:.*flush takes no arguments.*" err
1291 test_expect_success 'batch-command flush without --buffer' '
1292 echo "flush" >cmd &&
1293 test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
1294 grep "^fatal:.*flush is only for --buffer mode.*" err
1297 test_done