From 5c5b29b459dd6e169c9114910adca9203532f7d7 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 5 Oct 2021 16:36:07 -0400 Subject: [PATCH] cat-file: disable refs/replace with --batch-all-objects When we're enumerating all objects in the object database, it doesn't make sense to respect refs/replace. The point of this option is to enumerate all of the objects in the database at a low level. By definition we'd already show the replacement object's contents (under its real oid), and showing those contents under another oid is almost certainly working against what the user is trying to do. Note that you could make the same argument for something like: git show-index Signed-off-by: Junio C Hamano --- Documentation/git-cat-file.txt | 3 +- builtin/cat-file.c | 2 ++ t/t1006-cat-file.sh | 66 ++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 6467707c6e..27b27e2b30 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -96,7 +96,8 @@ OPTIONS any alternate object stores (not just reachable objects). Requires `--batch` or `--batch-check` be specified. By default, the objects are visited in order sorted by their hashes; see - also `--unordered` below. + also `--unordered` below. Objects are presented as-is, without + respecting the "replace" mechanism of linkgit:git-replace[1]. --buffer:: Normally batch output is flushed after each object is output, so diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 243fe6844b..b713be545e 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -529,6 +529,8 @@ static int batch_objects(struct batch_options *opt) if (has_promisor_remote()) warning("This repository uses promisor remotes. Some objects may not be loaded."); + read_replace_refs = 0; + cb.opt = opt; cb.expand = &data; cb.scratch = &output; diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index c77db35728..4a753705ec 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -617,4 +617,70 @@ test_expect_success 'cat-file --batch="batman" with --batch-all-objects will wor cmp expect actual ' +test_expect_success 'set up replacement object' ' + orig=$(git rev-parse HEAD) && + git cat-file commit $orig >orig && + { + cat orig && + echo extra + } >fake && + fake=$(git hash-object -t commit -w fake) && + orig_size=$(git cat-file -s $orig) && + fake_size=$(git cat-file -s $fake) && + git replace $orig $fake +' + +test_expect_success 'cat-file --batch respects replace objects' ' + git cat-file --batch >actual <<-EOF && + $orig + EOF + { + echo "$orig commit $fake_size" && + cat fake && + echo + } >expect && + test_cmp expect actual +' + +test_expect_success 'cat-file --batch-check respects replace objects' ' + git cat-file --batch-check >actual <<-EOF && + $orig + EOF + echo "$orig commit $fake_size" >expect && + test_cmp expect actual +' + +# Pull the entry for object with oid "$1" out of the output of +# "cat-file --batch", including its object content (which requires +# parsing and reading a set amount of bytes, hence perl). +extract_batch_output () { + perl -ne ' + BEGIN { $oid = shift } + if (/^$oid \S+ (\d+)$/) { + print; + read STDIN, my $buf, $1; + print $buf; + print "\n"; + } + ' "$@" +} + +test_expect_success 'cat-file --batch-all-objects --batch ignores replace' ' + git cat-file --batch-all-objects --batch >actual.raw && + extract_batch_output $orig actual && + { + echo "$orig commit $orig_size" && + cat orig && + echo + } >expect && + test_cmp expect actual +' + +test_expect_success 'cat-file --batch-all-objects --batch-check ignores replace' ' + git cat-file --batch-all-objects --batch-check >actual.raw && + grep ^$orig actual.raw >actual && + echo "$orig commit $orig_size" >expect && + test_cmp expect actual +' + test_done