2008-04-23 21:17:43 +02:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='git cat-file'
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
echo_without_newline () {
|
|
|
|
printf '%s' "$*"
|
|
|
|
}
|
|
|
|
|
|
|
|
strlen () {
|
|
|
|
echo_without_newline "$1" | wc -c | sed -e 's/^ *//'
|
|
|
|
}
|
|
|
|
|
|
|
|
maybe_remove_timestamp () {
|
|
|
|
if test -z "$2"; then
|
|
|
|
echo_without_newline "$1"
|
|
|
|
else
|
|
|
|
echo_without_newline "$(printf '%s\n' "$1" | sed -e 's/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//')"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
run_tests () {
|
|
|
|
type=$1
|
|
|
|
sha1=$2
|
|
|
|
size=$3
|
|
|
|
content=$4
|
|
|
|
pretty_content=$5
|
|
|
|
no_ts=$6
|
|
|
|
|
2008-04-23 21:17:47 +02:00
|
|
|
batch_output="$sha1 $type $size
|
|
|
|
$content"
|
|
|
|
|
2008-04-23 21:17:43 +02:00
|
|
|
test_expect_success "$type exists" '
|
|
|
|
git cat-file -e $sha1
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "Type of $type is correct" '
|
2013-07-10 13:36:43 +02:00
|
|
|
echo $type >expect &&
|
|
|
|
git cat-file -t $sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
2008-04-23 21:17:43 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "Size of $type is correct" '
|
2013-07-10 13:36:43 +02:00
|
|
|
echo $size >expect &&
|
|
|
|
git cat-file -s $sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
2008-04-23 21:17:43 +02:00
|
|
|
'
|
|
|
|
|
2015-05-03 16:30:02 +02:00
|
|
|
test_expect_success "Type of $type is correct using --allow-unknown-type" '
|
|
|
|
echo $type >expect &&
|
|
|
|
git cat-file -t --allow-unknown-type $sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "Size of $type is correct using --allow-unknown-type" '
|
|
|
|
echo $size >expect &&
|
|
|
|
git cat-file -s --allow-unknown-type $sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2008-04-23 21:17:43 +02:00
|
|
|
test -z "$content" ||
|
|
|
|
test_expect_success "Content of $type is correct" '
|
2013-07-10 13:36:43 +02:00
|
|
|
maybe_remove_timestamp "$content" $no_ts >expect &&
|
|
|
|
maybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts >actual &&
|
|
|
|
test_cmp expect actual
|
2008-04-23 21:17:43 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "Pretty content of $type is correct" '
|
2013-07-10 13:36:43 +02:00
|
|
|
maybe_remove_timestamp "$pretty_content" $no_ts >expect &&
|
|
|
|
maybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts >actual &&
|
|
|
|
test_cmp expect actual
|
2008-04-23 21:17:43 +02:00
|
|
|
'
|
2008-04-23 21:17:46 +02:00
|
|
|
|
2008-04-23 21:17:47 +02:00
|
|
|
test -z "$content" ||
|
|
|
|
test_expect_success "--batch output of $type is correct" '
|
2013-07-10 13:36:43 +02:00
|
|
|
maybe_remove_timestamp "$batch_output" $no_ts >expect &&
|
|
|
|
maybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts >actual &&
|
|
|
|
test_cmp expect actual
|
2008-04-23 21:17:47 +02:00
|
|
|
'
|
|
|
|
|
2008-04-23 21:17:46 +02:00
|
|
|
test_expect_success "--batch-check output of $type is correct" '
|
2013-07-10 13:36:43 +02:00
|
|
|
echo "$sha1 $type $size" >expect &&
|
|
|
|
echo_without_newline $sha1 | git cat-file --batch-check >actual &&
|
|
|
|
test_cmp expect actual
|
2008-04-23 21:17:46 +02:00
|
|
|
'
|
2013-07-10 13:45:47 +02:00
|
|
|
|
|
|
|
test_expect_success "custom --batch-check format" '
|
|
|
|
echo "$type $sha1" >expect &&
|
|
|
|
echo $sha1 | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
cat-file: only split on whitespace when %(rest) is used
Commit c334b87b (cat-file: split --batch input lines on whitespace,
2013-07-11) taught `cat-file --batch-check` to split input lines on
the first whitespace, and stash everything after the first token
into the %(rest) output format element. It claimed:
Object names cannot contain spaces, so any input with
spaces would have resulted in a "missing" line.
But that is not correct. Refs, object sha1s, and various peeling
suffixes cannot contain spaces, but some object names can. In
particular:
1. Tree paths like "[<tree>]:path with whitespace"
2. Reflog specifications like "@{2 days ago}"
3. Commit searches like "rev^{/grep me}" or ":/grep me"
To remain backwards compatible, we cannot split on whitespace by
default, hence we will ship 1.8.4 with the commit reverted.
Resurrect its attempt but in a weaker form; only do the splitting
when "%(rest)" is used in the output format. Since that element did
not exist at all before c334b87, old scripts cannot be affected.
The existence of object names with spaces does mean that you
cannot reliably do:
echo ":path with space and other data" |
git cat-file --batch-check="%(objectname) %(rest)"
as it would split the path and feed only ":path" to get_sha1. But
that command is nonsensical. If you wanted to see "and other data"
in "%(rest)", git cannot possibly know where the filename ends and
the "rest" begins.
It might be more robust to have something like "-z" to separate the
input elements. But this patch is still a reasonable step before
having that. It makes the easy cases easy; people who do not care
about %(rest) do not have to consider it, and the %(rest) code
handles the spaces and newlines of "rev-list --objects" correctly.
Hard cases remain hard but possible (if you might get whitespace in
your input, you do not get to use %(rest) and must split and join
the output yourself using more flexible tools). And most
importantly, it does not preclude us from having different splitting
rules later if a "-z" (or similar) option is added. So we can make
the hard cases easier later, if we choose to.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-08-02 13:59:07 +02:00
|
|
|
|
|
|
|
test_expect_success '--batch-check with %(rest)' '
|
|
|
|
echo "$type this is some extra content" >expect &&
|
|
|
|
echo "$sha1 this is some extra content" |
|
|
|
|
git cat-file --batch-check="%(objecttype) %(rest)" >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
cat-file: handle --batch format with missing type/size
Commit 98e2092 taught cat-file to stream blobs with --batch,
which requires that we look up the object type before
loading it into memory. As a result, we now print the
object header from information in sha1_object_info, and the
actual contents from the read_sha1_file. We double-check
that the information we printed in the header matches the
content we are about to show.
Later, commit 93d2a60 allowed custom header lines for
--batch, and commit 5b08640 made type lookups optional. As a
result, specifying a header line without the type or size
means that we will not look up those items at all.
This causes our double-checking to erroneously die with an
error; we think the type or size has changed, when in fact
it was simply left at "0".
For the size, we can fix this by only doing the consistency
double-check when we have retrieved the size via
sha1_object_info. In the case that we have not retrieved the
value, that means we also did not print it, so there is
nothing for us to check that we are consistent with.
We could do the same for the type. However, besides our
consistency check, we also care about the type in deciding
whether to stream or not. So instead of handling the case
where we do not know the type, this patch instead makes sure
that we always trigger a type lookup when we are printing,
so that even a format without the type will stream as we
would in the normal case.
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-12-12 00:15:50 +01:00
|
|
|
|
|
|
|
test -z "$content" ||
|
|
|
|
test_expect_success "--batch without type ($type)" '
|
|
|
|
{
|
|
|
|
echo "$size" &&
|
|
|
|
maybe_remove_timestamp "$content" $no_ts
|
|
|
|
} >expect &&
|
|
|
|
echo $sha1 | git cat-file --batch="%(objectsize)" >actual.full &&
|
|
|
|
maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test -z "$content" ||
|
|
|
|
test_expect_success "--batch without size ($type)" '
|
|
|
|
{
|
|
|
|
echo "$type" &&
|
|
|
|
maybe_remove_timestamp "$content" $no_ts
|
|
|
|
} >expect &&
|
|
|
|
echo $sha1 | git cat-file --batch="%(objecttype)" >actual.full &&
|
|
|
|
maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
2008-04-23 21:17:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
hello_content="Hello World"
|
|
|
|
hello_size=$(strlen "$hello_content")
|
|
|
|
hello_sha1=$(echo_without_newline "$hello_content" | git hash-object --stdin)
|
|
|
|
|
|
|
|
test_expect_success "setup" '
|
|
|
|
echo_without_newline "$hello_content" > hello &&
|
|
|
|
git update-index --add hello
|
|
|
|
'
|
|
|
|
|
|
|
|
run_tests 'blob' $hello_sha1 $hello_size "$hello_content" "$hello_content"
|
|
|
|
|
cat-file: only split on whitespace when %(rest) is used
Commit c334b87b (cat-file: split --batch input lines on whitespace,
2013-07-11) taught `cat-file --batch-check` to split input lines on
the first whitespace, and stash everything after the first token
into the %(rest) output format element. It claimed:
Object names cannot contain spaces, so any input with
spaces would have resulted in a "missing" line.
But that is not correct. Refs, object sha1s, and various peeling
suffixes cannot contain spaces, but some object names can. In
particular:
1. Tree paths like "[<tree>]:path with whitespace"
2. Reflog specifications like "@{2 days ago}"
3. Commit searches like "rev^{/grep me}" or ":/grep me"
To remain backwards compatible, we cannot split on whitespace by
default, hence we will ship 1.8.4 with the commit reverted.
Resurrect its attempt but in a weaker form; only do the splitting
when "%(rest)" is used in the output format. Since that element did
not exist at all before c334b87, old scripts cannot be affected.
The existence of object names with spaces does mean that you
cannot reliably do:
echo ":path with space and other data" |
git cat-file --batch-check="%(objectname) %(rest)"
as it would split the path and feed only ":path" to get_sha1. But
that command is nonsensical. If you wanted to see "and other data"
in "%(rest)", git cannot possibly know where the filename ends and
the "rest" begins.
It might be more robust to have something like "-z" to separate the
input elements. But this patch is still a reasonable step before
having that. It makes the easy cases easy; people who do not care
about %(rest) do not have to consider it, and the %(rest) code
handles the spaces and newlines of "rev-list --objects" correctly.
Hard cases remain hard but possible (if you might get whitespace in
your input, you do not get to use %(rest) and must split and join
the output yourself using more flexible tools). And most
importantly, it does not preclude us from having different splitting
rules later if a "-z" (or similar) option is added. So we can make
the hard cases easier later, if we choose to.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-08-02 13:59:07 +02:00
|
|
|
test_expect_success '--batch-check without %(rest) considers whole line' '
|
|
|
|
echo "$hello_sha1 blob $hello_size" >expect &&
|
|
|
|
git update-index --add --cacheinfo 100644 $hello_sha1 "white space" &&
|
|
|
|
test_when_finished "git update-index --remove \"white space\"" &&
|
|
|
|
echo ":white space" | git cat-file --batch-check >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2018-09-13 07:17:37 +02:00
|
|
|
test_oid_init
|
|
|
|
|
2008-04-23 21:17:43 +02:00
|
|
|
tree_sha1=$(git write-tree)
|
2018-09-13 07:17:37 +02:00
|
|
|
tree_size=$(($(test_oid rawsz) + 13))
|
2008-04-23 21:17:43 +02:00
|
|
|
tree_pretty_content="100644 blob $hello_sha1 hello"
|
|
|
|
|
|
|
|
run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content"
|
|
|
|
|
2013-04-12 00:36:10 +02:00
|
|
|
commit_message="Initial commit"
|
2008-04-23 21:17:43 +02:00
|
|
|
commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1)
|
2018-09-13 07:17:37 +02:00
|
|
|
commit_size=$(($(test_oid hexsz) + 137))
|
2008-04-23 21:17:43 +02:00
|
|
|
commit_content="tree $tree_sha1
|
|
|
|
author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000
|
|
|
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000
|
|
|
|
|
|
|
|
$commit_message"
|
|
|
|
|
|
|
|
run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" 1
|
|
|
|
|
|
|
|
tag_header_without_timestamp="object $hello_sha1
|
|
|
|
type blob
|
|
|
|
tag hellotag
|
|
|
|
tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
|
|
|
|
tag_description="This is a tag"
|
|
|
|
tag_content="$tag_header_without_timestamp 0000000000 +0000
|
|
|
|
|
|
|
|
$tag_description"
|
|
|
|
|
|
|
|
tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
|
|
|
|
tag_size=$(strlen "$tag_content")
|
|
|
|
|
cat-file: print tags raw for "cat-file -p"
When "cat-file -p" prints commits, it shows them in their
raw format, since git's format is already human-readable.
For tags, however, we print the whole thing raw except for
one thing: we convert the timestamp on the tagger line into a
human-readable date.
This dates all the way back to a0f15fa (Pretty-print tagger
dates, 2006-03-01). At that time there was no other way to
pretty-print a tag. These days, however, neither of those
matters much. The normal way to pretty-print a tag is with
"git show", which is much more flexible than "cat-file -p".
Commit a0f15fa also built "verify-tag --verbose" (and
subsequently "tag -v") around the "cat-file -p" output.
However, that behavior was lost in commit 62e09ce (Make git
tag a builtin, 2007-07-20), and we went back to printing
the raw tag contents. Nobody seems to have noticed the bug
since then (and it is arguably a saner behavior anyway, as
it shows the actual bytes for which we verified the
signature).
Let's drop the tagger-date formatting for "cat-file -p". It
makes us more consistent with cat-file's commit
pretty-printer, and as a bonus, we can drop the hand-rolled
tag parsing code in cat-file (which happened to behave
inconsistently with the tag pretty-printing code elsewhere).
This is a change of output format, so it's possible that
some callers could considered this a regression. However,
the original behavior was arguably a bug (due to the
inconsistency with commits), likely nobody was relying on it
(even we do not use it ourselves these days), and anyone
relying on the "-p" pretty-printer should be able to expect
a change in the output format (i.e., while "cat-file" is
plumbing, the output format of "-p" was never guaranteed to
be stable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-17 23:00:48 +02:00
|
|
|
run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
|
2008-04-23 21:17:43 +02:00
|
|
|
|
|
|
|
test_expect_success \
|
|
|
|
"Reach a blob from a tag pointing to it" \
|
|
|
|
"test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""
|
|
|
|
|
2008-04-23 21:17:47 +02:00
|
|
|
for batch in batch batch-check
|
2008-04-23 21:17:46 +02:00
|
|
|
do
|
2008-04-23 21:17:47 +02:00
|
|
|
for opt in t s e p
|
|
|
|
do
|
|
|
|
test_expect_success "Passing -$opt with --$batch fails" '
|
|
|
|
test_must_fail git cat-file --$batch -$opt $hello_sha1
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "Passing --$batch with -$opt fails" '
|
|
|
|
test_must_fail git cat-file -$opt --$batch $hello_sha1
|
|
|
|
'
|
|
|
|
done
|
|
|
|
|
|
|
|
test_expect_success "Passing <type> with --$batch fails" '
|
|
|
|
test_must_fail git cat-file --$batch blob $hello_sha1
|
2008-04-23 21:17:46 +02:00
|
|
|
'
|
|
|
|
|
2008-04-23 21:17:47 +02:00
|
|
|
test_expect_success "Passing --$batch with <type> fails" '
|
|
|
|
test_must_fail git cat-file blob --$batch $hello_sha1
|
2008-04-23 21:17:46 +02:00
|
|
|
'
|
|
|
|
|
2008-04-23 21:17:47 +02:00
|
|
|
test_expect_success "Passing sha1 with --$batch fails" '
|
|
|
|
test_must_fail git cat-file --$batch $hello_sha1
|
|
|
|
'
|
|
|
|
done
|
2008-04-23 21:17:46 +02:00
|
|
|
|
2015-05-20 19:03:40 +02:00
|
|
|
for opt in t s e p
|
|
|
|
do
|
|
|
|
test_expect_success "Passing -$opt with --follow-symlinks fails" '
|
|
|
|
test_must_fail git cat-file --follow-symlinks -$opt $hello_sha1
|
|
|
|
'
|
|
|
|
done
|
|
|
|
|
2008-06-09 02:02:21 +02:00
|
|
|
test_expect_success "--batch-check for a non-existent named object" '
|
|
|
|
test "foobar42 missing
|
|
|
|
foobar84 missing" = \
|
|
|
|
"$( ( echo foobar42; echo_without_newline foobar84; ) | git cat-file --batch-check)"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "--batch-check for a non-existent hash" '
|
|
|
|
test "0000000000000000000000000000000000000042 missing
|
|
|
|
0000000000000000000000000000000000000084 missing" = \
|
|
|
|
"$( ( echo 0000000000000000000000000000000000000042;
|
2018-10-05 23:54:03 +02:00
|
|
|
echo_without_newline 0000000000000000000000000000000000000084; ) |
|
|
|
|
git cat-file --batch-check)"
|
2008-06-09 02:02:21 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "--batch for an existent and a non-existent hash" '
|
|
|
|
test "$tag_sha1 tag $tag_size
|
|
|
|
$tag_content
|
|
|
|
0000000000000000000000000000000000000000 missing" = \
|
|
|
|
"$( ( echo $tag_sha1;
|
2018-10-05 23:54:03 +02:00
|
|
|
echo_without_newline 0000000000000000000000000000000000000000; ) |
|
|
|
|
git cat-file --batch)"
|
2008-04-23 21:17:46 +02:00
|
|
|
'
|
|
|
|
|
2016-08-09 10:53:38 +02:00
|
|
|
test_expect_success "--batch-check for an empty line" '
|
2008-04-23 21:17:46 +02:00
|
|
|
test " missing" = "$(echo | git cat-file --batch-check)"
|
|
|
|
'
|
|
|
|
|
2013-11-06 19:00:57 +01:00
|
|
|
test_expect_success 'empty --batch-check notices missing object' '
|
2018-05-13 04:24:13 +02:00
|
|
|
echo "$ZERO_OID missing" >expect &&
|
|
|
|
echo "$ZERO_OID" | git cat-file --batch-check="" >actual &&
|
2013-11-06 19:00:57 +01:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2008-04-23 21:17:47 +02:00
|
|
|
batch_input="$hello_sha1
|
|
|
|
$commit_sha1
|
|
|
|
$tag_sha1
|
|
|
|
deadbeef
|
|
|
|
|
|
|
|
"
|
|
|
|
|
|
|
|
batch_output="$hello_sha1 blob $hello_size
|
|
|
|
$hello_content
|
|
|
|
$commit_sha1 commit $commit_size
|
|
|
|
$commit_content
|
|
|
|
$tag_sha1 tag $tag_size
|
|
|
|
$tag_content
|
|
|
|
deadbeef missing
|
|
|
|
missing"
|
|
|
|
|
2008-05-23 16:19:43 +02:00
|
|
|
test_expect_success '--batch with multiple sha1s gives correct format' '
|
|
|
|
test "$(maybe_remove_timestamp "$batch_output" 1)" = "$(maybe_remove_timestamp "$(echo_without_newline "$batch_input" | git cat-file --batch)" 1)"
|
|
|
|
'
|
2008-04-23 21:17:47 +02:00
|
|
|
|
2008-04-23 21:17:46 +02:00
|
|
|
batch_check_input="$hello_sha1
|
|
|
|
$tree_sha1
|
|
|
|
$commit_sha1
|
|
|
|
$tag_sha1
|
|
|
|
deadbeef
|
|
|
|
|
|
|
|
"
|
|
|
|
|
|
|
|
batch_check_output="$hello_sha1 blob $hello_size
|
|
|
|
$tree_sha1 tree $tree_size
|
|
|
|
$commit_sha1 commit $commit_size
|
|
|
|
$tag_sha1 tag $tag_size
|
|
|
|
deadbeef missing
|
|
|
|
missing"
|
|
|
|
|
|
|
|
test_expect_success "--batch-check with multiple sha1s gives correct format" '
|
|
|
|
test "$batch_check_output" = \
|
|
|
|
"$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)"
|
|
|
|
'
|
|
|
|
|
2013-12-21 15:25:22 +01:00
|
|
|
test_expect_success 'setup blobs which are likely to delta' '
|
2018-03-24 08:44:42 +01:00
|
|
|
test-tool genrandom foo 10240 >foo &&
|
2013-12-21 15:25:22 +01:00
|
|
|
{ cat foo; echo plus; } >foo-plus &&
|
|
|
|
git add foo foo-plus &&
|
|
|
|
git commit -m foo &&
|
|
|
|
cat >blobs <<-\EOF
|
|
|
|
HEAD:foo
|
|
|
|
HEAD:foo-plus
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'confirm that neither loose blob is a delta' '
|
2015-03-20 11:07:15 +01:00
|
|
|
cat >expect <<-EOF &&
|
2018-05-13 04:24:13 +02:00
|
|
|
$ZERO_OID
|
|
|
|
$ZERO_OID
|
2013-12-21 15:25:22 +01:00
|
|
|
EOF
|
|
|
|
git cat-file --batch-check="%(deltabase)" <blobs >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
# To avoid relying too much on the current delta heuristics,
|
|
|
|
# we will check only that one of the two objects is a delta
|
|
|
|
# against the other, but not the order. We can do so by just
|
|
|
|
# asking for the base of both, and checking whether either
|
|
|
|
# sha1 appears in the output.
|
|
|
|
test_expect_success '%(deltabase) reports packed delta bases' '
|
|
|
|
git repack -ad &&
|
|
|
|
git cat-file --batch-check="%(deltabase)" <blobs >actual &&
|
|
|
|
{
|
|
|
|
grep "$(git rev-parse HEAD:foo)" actual ||
|
|
|
|
grep "$(git rev-parse HEAD:foo-plus)" actual
|
|
|
|
}
|
|
|
|
'
|
|
|
|
|
2015-05-03 16:30:02 +02:00
|
|
|
bogus_type="bogus"
|
|
|
|
bogus_content="bogus"
|
|
|
|
bogus_size=$(strlen "$bogus_content")
|
|
|
|
bogus_sha1=$(echo_without_newline "$bogus_content" | git hash-object -t $bogus_type --literally -w --stdin)
|
|
|
|
|
|
|
|
test_expect_success "Type of broken object is correct" '
|
|
|
|
echo $bogus_type >expect &&
|
|
|
|
git cat-file -t --allow-unknown-type $bogus_sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "Size of broken object is correct" '
|
|
|
|
echo $bogus_size >expect &&
|
|
|
|
git cat-file -s --allow-unknown-type $bogus_sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
bogus_type="abcdefghijklmnopqrstuvwxyz1234679"
|
|
|
|
bogus_content="bogus"
|
|
|
|
bogus_size=$(strlen "$bogus_content")
|
|
|
|
bogus_sha1=$(echo_without_newline "$bogus_content" | git hash-object -t $bogus_type --literally -w --stdin)
|
|
|
|
|
|
|
|
test_expect_success "Type of broken object is correct when type is large" '
|
|
|
|
echo $bogus_type >expect &&
|
|
|
|
git cat-file -t --allow-unknown-type $bogus_sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "Size of large broken object is correct when type is large" '
|
|
|
|
echo $bogus_size >expect &&
|
|
|
|
git cat-file -s --allow-unknown-type $bogus_sha1 >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2015-05-20 19:03:40 +02:00
|
|
|
# Tests for git cat-file --follow-symlinks
|
|
|
|
test_expect_success 'prep for symlink tests' '
|
|
|
|
echo_without_newline "$hello_content" >morx &&
|
|
|
|
test_ln_s_add morx same-dir-link &&
|
|
|
|
test_ln_s_add dir link-to-dir &&
|
|
|
|
test_ln_s_add ../fleem out-of-repo-link &&
|
|
|
|
test_ln_s_add .. out-of-repo-link-dir &&
|
|
|
|
test_ln_s_add same-dir-link link-to-link &&
|
|
|
|
test_ln_s_add nope broken-same-dir-link &&
|
|
|
|
mkdir dir &&
|
|
|
|
test_ln_s_add ../morx dir/parent-dir-link &&
|
|
|
|
test_ln_s_add .. dir/link-dir &&
|
|
|
|
test_ln_s_add ../../escape dir/out-of-repo-link &&
|
|
|
|
test_ln_s_add ../.. dir/out-of-repo-link-dir &&
|
|
|
|
test_ln_s_add nope dir/broken-link-in-dir &&
|
|
|
|
mkdir dir/subdir &&
|
|
|
|
test_ln_s_add ../../morx dir/subdir/grandparent-dir-link &&
|
|
|
|
test_ln_s_add ../../../great-escape dir/subdir/out-of-repo-link &&
|
|
|
|
test_ln_s_add ../../.. dir/subdir/out-of-repo-link-dir &&
|
|
|
|
test_ln_s_add ../../../ dir/subdir/out-of-repo-link-dir-trailing &&
|
|
|
|
test_ln_s_add ../parent-dir-link dir/subdir/parent-dir-link-to-link &&
|
|
|
|
echo_without_newline "$hello_content" >dir/subdir/ind2 &&
|
|
|
|
echo_without_newline "$hello_content" >dir/ind1 &&
|
|
|
|
test_ln_s_add dir dirlink &&
|
|
|
|
test_ln_s_add dir/subdir subdirlink &&
|
|
|
|
test_ln_s_add subdir/ind2 dir/link-to-child &&
|
|
|
|
test_ln_s_add dir/link-to-child link-to-down-link &&
|
|
|
|
test_ln_s_add dir/.. up-down &&
|
|
|
|
test_ln_s_add dir/../ up-down-trailing &&
|
|
|
|
test_ln_s_add dir/../morx up-down-file &&
|
|
|
|
test_ln_s_add dir/../../morx up-up-down-file &&
|
|
|
|
test_ln_s_add subdirlink/../../morx up-two-down-file &&
|
|
|
|
test_ln_s_add loop1 loop2 &&
|
|
|
|
test_ln_s_add loop2 loop1 &&
|
|
|
|
git add morx dir/subdir/ind2 dir/ind1 &&
|
|
|
|
git commit -am "test" &&
|
|
|
|
echo $hello_sha1 blob $hello_size >found
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for non-links' '
|
|
|
|
echo HEAD:morx | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual &&
|
|
|
|
echo HEAD:nope missing >expect &&
|
|
|
|
echo HEAD:nope | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for in-repo, same-dir links' '
|
|
|
|
echo HEAD:same-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for in-repo, links to dirs' '
|
|
|
|
echo HEAD:link-to-dir/ind1 | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for broken in-repo, same-dir links' '
|
|
|
|
echo dangling 25 >expect &&
|
|
|
|
echo HEAD:broken-same-dir-link >>expect &&
|
|
|
|
echo HEAD:broken-same-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for same-dir links-to-links' '
|
|
|
|
echo HEAD:link-to-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for parent-dir links' '
|
|
|
|
echo HEAD:dir/parent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual &&
|
|
|
|
echo notdir 29 >expect &&
|
|
|
|
echo HEAD:dir/parent-dir-link/nope >>expect &&
|
|
|
|
echo HEAD:dir/parent-dir-link/nope | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for .. links' '
|
|
|
|
echo dangling 22 >expect &&
|
|
|
|
echo HEAD:dir/link-dir/nope >>expect &&
|
|
|
|
echo HEAD:dir/link-dir/nope | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo HEAD:dir/link-dir/morx | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual &&
|
|
|
|
echo dangling 27 >expect &&
|
|
|
|
echo HEAD:dir/broken-link-in-dir >>expect &&
|
|
|
|
echo HEAD:dir/broken-link-in-dir | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for ../.. links' '
|
|
|
|
echo notdir 41 >expect &&
|
|
|
|
echo HEAD:dir/subdir/grandparent-dir-link/nope >>expect &&
|
|
|
|
echo HEAD:dir/subdir/grandparent-dir-link/nope | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo HEAD:dir/subdir/grandparent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual &&
|
|
|
|
echo HEAD:dir/subdir/parent-dir-link-to-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for dir/ links' '
|
|
|
|
echo dangling 17 >expect &&
|
|
|
|
echo HEAD:dirlink/morx >>expect &&
|
|
|
|
echo HEAD:dirlink/morx | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo $hello_sha1 blob $hello_size >expect &&
|
|
|
|
echo HEAD:dirlink/ind1 | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for dir/subdir links' '
|
|
|
|
echo dangling 20 >expect &&
|
|
|
|
echo HEAD:subdirlink/morx >>expect &&
|
|
|
|
echo HEAD:subdirlink/morx | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo HEAD:subdirlink/ind2 | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for dir ->subdir links' '
|
|
|
|
echo notdir 27 >expect &&
|
|
|
|
echo HEAD:dir/link-to-child/morx >>expect &&
|
|
|
|
echo HEAD:dir/link-to-child/morx | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo HEAD:dir/link-to-child | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual &&
|
|
|
|
echo HEAD:link-to-down-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks' '
|
|
|
|
echo symlink 8 >expect &&
|
|
|
|
echo ../fleem >>expect &&
|
|
|
|
echo HEAD:out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo symlink 2 >expect &&
|
|
|
|
echo .. >>expect &&
|
|
|
|
echo HEAD:out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks in dirs' '
|
|
|
|
echo symlink 9 >expect &&
|
|
|
|
echo ../escape >>expect &&
|
|
|
|
echo HEAD:dir/out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo symlink 2 >expect &&
|
|
|
|
echo .. >>expect &&
|
|
|
|
echo HEAD:dir/out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks in subdirs' '
|
|
|
|
echo symlink 15 >expect &&
|
|
|
|
echo ../great-escape >>expect &&
|
|
|
|
echo HEAD:dir/subdir/out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo symlink 2 >expect &&
|
|
|
|
echo .. >>expect &&
|
|
|
|
echo HEAD:dir/subdir/out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo symlink 3 >expect &&
|
|
|
|
echo ../ >>expect &&
|
|
|
|
echo HEAD:dir/subdir/out-of-repo-link-dir-trailing | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlinks works for symlinks with internal ..' '
|
|
|
|
echo HEAD: | git cat-file --batch-check >expect &&
|
|
|
|
echo HEAD:up-down | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo HEAD:up-down-trailing | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo HEAD:up-down-file | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual &&
|
|
|
|
echo symlink 7 >expect &&
|
|
|
|
echo ../morx >>expect &&
|
|
|
|
echo HEAD:up-up-down-file | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
echo HEAD:up-two-down-file | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp found actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch-check --follow-symlink breaks loops' '
|
|
|
|
echo loop 10 >expect &&
|
|
|
|
echo HEAD:loop1 >>expect &&
|
|
|
|
echo HEAD:loop1 | git cat-file --batch-check --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git cat-file --batch --follow-symlink returns correct sha and mode' '
|
|
|
|
echo HEAD:morx | git cat-file --batch >expect &&
|
|
|
|
echo HEAD:morx | git cat-file --batch --follow-symlinks >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
2015-06-01 21:45:16 +02:00
|
|
|
|
2015-06-22 12:45:59 +02:00
|
|
|
test_expect_success 'cat-file --batch-all-objects shows all objects' '
|
2015-06-22 13:06:32 +02:00
|
|
|
# make new repos so we know the full set of objects; we will
|
2015-06-22 12:45:59 +02:00
|
|
|
# also make sure that there are some packed and some loose
|
2018-08-11 01:16:40 +02:00
|
|
|
# objects, some referenced and some not, some duplicates, and that
|
|
|
|
# there are some available only via alternates.
|
2015-06-22 12:45:59 +02:00
|
|
|
git init all-one &&
|
|
|
|
(
|
|
|
|
cd all-one &&
|
|
|
|
echo content >file &&
|
|
|
|
git add file &&
|
|
|
|
git commit -qm base &&
|
|
|
|
git rev-parse HEAD HEAD^{tree} HEAD:file &&
|
|
|
|
git repack -ad &&
|
|
|
|
echo not-cloned | git hash-object -w --stdin
|
|
|
|
) >expect.unsorted &&
|
|
|
|
git clone -s all-one all-two &&
|
|
|
|
(
|
|
|
|
cd all-two &&
|
|
|
|
echo local-unref | git hash-object -w --stdin
|
|
|
|
) >>expect.unsorted &&
|
2018-08-11 01:16:40 +02:00
|
|
|
git -C all-two rev-parse HEAD:file |
|
|
|
|
git -C all-two pack-objects .git/objects/pack/pack &&
|
2015-06-22 12:45:59 +02:00
|
|
|
sort <expect.unsorted >expect &&
|
|
|
|
git -C all-two cat-file --batch-all-objects \
|
2015-06-22 13:06:32 +02:00
|
|
|
--batch-check="%(objectname)" >actual &&
|
2015-06-22 12:45:59 +02:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
cat-file: support "unordered" output for --batch-all-objects
If you're going to access the contents of every object in a
packfile, it's generally much more efficient to do so in
pack order, rather than in hash order. That increases the
locality of access within the packfile, which in turn is
friendlier to the delta base cache, since the packfile puts
related deltas next to each other. By contrast, hash order
is effectively random, since the sha1 has no discernible
relationship to the content.
This patch introduces an "--unordered" option to cat-file
which iterates over packs in pack-order under the hood. You
can see the results when dumping all of the file content:
$ time ./git cat-file --batch-all-objects --buffer --batch | wc -c
6883195596
real 0m44.491s
user 0m42.902s
sys 0m5.230s
$ time ./git cat-file --unordered \
--batch-all-objects --buffer --batch | wc -c
6883195596
real 0m6.075s
user 0m4.774s
sys 0m3.548s
Same output, different order, way faster. The same speed-up
applies even if you end up accessing the object content in a
different process, like:
git cat-file --batch-all-objects --buffer --batch-check |
grep blob |
git cat-file --batch='%(objectname) %(rest)' |
wc -c
Adding "--unordered" to the first command drops the runtime
in git.git from 24s to 3.5s.
Side note: there are actually further speedups available
for doing it all in-process now. Since we are outputting
the object content during the actual pack iteration, we
know where to find the object and could skip the extra
lookup done by oid_object_info(). This patch stops short
of that optimization since the underlying API isn't ready
for us to make those sorts of direct requests.
So if --unordered is so much better, why not make it the
default? Two reasons:
1. We've promised in the documentation that --batch-all-objects
outputs in hash order. Since cat-file is plumbing,
people may be relying on that default, and we can't
change it.
2. It's actually _slower_ for some cases. We have to
compute the pack revindex to walk in pack order. And
our de-duplication step uses an oidset, rather than a
sort-and-dedup, which can end up being more expensive.
If we're just accessing the type and size of each
object, for example, like:
git cat-file --batch-all-objects --buffer --batch-check
my best-of-five warm cache timings go from 900ms to
1100ms using --unordered. Though it's possible in a
cold-cache or under memory pressure that we could do
better, since we'd have better locality within the
packfile.
And one final question: why is it "--unordered" and not
"--pack-order"? The answer is again two-fold:
1. "pack order" isn't a well-defined thing across the
whole set of objects. We're hitting loose objects, as
well as objects in multiple packs, and the only
ordering we're promising is _within_ a single pack. The
rest is apparently random.
2. The point here is optimization. So we don't want to
promise any particular ordering, but only to say that
we will choose an ordering which is likely to be
efficient for accessing the object content. That leaves
the door open for further changes in the future without
having to add another compatibility option.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-11 01:24:57 +02:00
|
|
|
# The only user-visible difference is that the objects are no longer sorted,
|
|
|
|
# and the resulting sort order is undefined. So we can only check that it
|
|
|
|
# produces the same objects as the ordered case, but that at least exercises
|
|
|
|
# the code.
|
|
|
|
test_expect_success 'cat-file --unordered works' '
|
|
|
|
git -C all-two cat-file --batch-all-objects --unordered \
|
|
|
|
--batch-check="%(objectname)" >actual.unsorted &&
|
|
|
|
sort <actual.unsorted >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2008-04-23 21:17:43 +02:00
|
|
|
test_done
|