]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'ps/cat-file-filter-batch'
authorJunio C Hamano <gitster@pobox.com>
Wed, 16 Apr 2025 20:54:20 +0000 (13:54 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 16 Apr 2025 20:54:21 +0000 (13:54 -0700)
"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

1  2 
Documentation/git-cat-file.adoc
builtin/pack-objects.c
builtin/rev-list.c
pack-bitmap.c
pack-bitmap.h
reachable.c
t/t1006-cat-file.sh

Simple merge
Simple merge
Simple merge
diff --cc pack-bitmap.c
Simple merge
diff --cc pack-bitmap.h
Simple merge
diff --cc reachable.c
Simple merge
index aa64678c64992a4cbab70edf75d7f6d4b51b24c7,98638fa2b9c950a24180558c0fd702be0b532fe0..ce8b27bf548fb750debff13385e51a68cfb8b99c
@@@ -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" <expected.excluded >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