From: Junio C Hamano Date: Wed, 16 Apr 2025 20:54:20 +0000 (-0700) Subject: Merge branch 'ps/cat-file-filter-batch' X-Git-Tag: v2.50.0-rc0~101 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a271b05066a1fd2c3a62508d9908d6c5df14a1cb;p=thirdparty%2Fgit.git Merge branch 'ps/cat-file-filter-batch' "git cat-file --batch" and friends learned to allow "--filter=" to omit certain objects, just like the transport layer does. * ps/cat-file-filter-batch: builtin/cat-file: use bitmaps to efficiently filter by object type builtin/cat-file: deduplicate logic to iterate over all objects pack-bitmap: introduce function to check whether a pack is bitmapped pack-bitmap: add function to iterate over filtered bitmapped objects pack-bitmap: allow passing payloads to `show_reachable_fn()` builtin/cat-file: support "object:type=" objects filter builtin/cat-file: support "blob:limit=" objects filter builtin/cat-file: support "blob:none" objects filter builtin/cat-file: wire up an option to filter objects builtin/cat-file: introduce function to report object status builtin/cat-file: rename variable that tracks usage --- a271b05066a1fd2c3a62508d9908d6c5df14a1cb diff --cc t/t1006-cat-file.sh index aa64678c64,98638fa2b9..ce8b27bf54 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@@ -1398,16 -1345,111 +1398,115 @@@ $? == 0 or die "\$?=$?" expect="$hello_oid blob $hello_size" -test_expect_success PERL '--batch-check is unbuffered by default' ' - perl -e "$script" -- --batch-check $hello_oid "$expect" +test_lazy_prereq PERL_IPC_OPEN2 ' + perl -MIPC::Open2 -e "exit 0" +' + +test_expect_success PERL_IPC_OPEN2 '--batch-check is unbuffered by default' ' + perl -e "$perl_script" -- --batch-check $hello_oid "$expect" ' -test_expect_success PERL '--batch-command info is unbuffered by default' ' - perl -e "$script" -- --batch-command $hello_oid "$expect" "info " +test_expect_success PERL_IPC_OPEN2 '--batch-command info is unbuffered by default' ' + perl -e "$perl_script" -- --batch-command $hello_oid "$expect" "info " ' + test_expect_success 'setup for objects filter' ' + git init repo && + ( + # Seed the repository with four different sets of objects: + # + # - The first set is fully packed and has a bitmap. + # - The second set is packed, but has no bitmap. + # - The third set is loose. + # - The fourth set is loose and contains big objects. + # + # This ensures that we cover all these types as expected. + cd repo && + test_commit first && + git repack -Adb && + test_commit second && + git repack -d && + test_commit third && + + for n in 1000 10000 + do + printf "%"$n"s" X >large.$n || return 1 + done && + git add large.* && + git commit -m fourth + ) + ' + + test_expect_success 'objects filter with unknown option' ' + cat >expect <<-EOF && + fatal: invalid filter-spec ${SQ}unknown${SQ} + EOF + test_must_fail git -C repo cat-file --filter=unknown 2>err && + test_cmp expect err + ' + + for option in sparse:oid=1234 tree:1 sparse:path=x + do + test_expect_success "objects filter with unsupported option $option" ' + case "$option" in + tree:1) + echo "usage: objects filter not supported: ${SQ}tree${SQ}" >expect + ;; + sparse:path=x) + echo "fatal: sparse:path filters support has been dropped" >expect + ;; + *) + option_name=$(echo "$option" | cut -d= -f1) && + printf "usage: objects filter not supported: ${SQ}%s${SQ}\n" "$option_name" >expect + ;; + esac && + test_must_fail git -C repo cat-file --filter=$option 2>err && + test_cmp expect err + ' + done + + test_expect_success 'objects filter: disabled' ' + git -C repo cat-file --batch-check="%(objectname)" --batch-all-objects --no-filter >actual && + sort actual >actual.sorted && + git -C repo rev-list --objects --no-object-names --all >expect && + sort expect >expect.sorted && + test_cmp expect.sorted actual.sorted + ' + + test_objects_filter () { + filter="$1" + + test_expect_success "objects filter: $filter" ' + git -C repo cat-file --batch-check="%(objectname)" --batch-all-objects --filter="$filter" >actual && + sort actual >actual.sorted && + git -C repo rev-list --objects --no-object-names --all --filter="$filter" --filter-provided-objects >expect && + sort expect >expect.sorted && + test_cmp expect.sorted actual.sorted + ' + + test_expect_success "objects filter prints excluded objects: $filter" ' + # Find all objects that would be excluded by the current filter. + git -C repo rev-list --objects --no-object-names --all >all && + git -C repo rev-list --objects --no-object-names --all --filter="$filter" --filter-provided-objects >filtered && + sort all >all.sorted && + sort filtered >filtered.sorted && + comm -23 all.sorted filtered.sorted >expected.excluded && + test_line_count -gt 0 expected.excluded && + + git -C repo cat-file --batch-check="%(objectname)" --filter="$filter" actual && + awk "/excluded/{ print \$1 }" actual | sort >actual.excluded && + test_cmp expected.excluded actual.excluded + ' + } + + test_objects_filter "blob:none" + test_objects_filter "blob:limit=1" + test_objects_filter "blob:limit=500" + test_objects_filter "blob:limit=1000" + test_objects_filter "blob:limit=1k" + test_objects_filter "object:type=blob" + test_objects_filter "object:type=commit" + test_objects_filter "object:type=tag" + test_objects_filter "object:type=tree" + test_done