| #!/bin/sh |
| |
| test_description='git log for a path with Bloom filters' |
| GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
| export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
| |
| . ./test-lib.sh |
| . "$TEST_DIRECTORY"/lib-chunk.sh |
| |
| GIT_TEST_COMMIT_GRAPH=0 |
| GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 |
| |
| test_expect_success 'setup test - repo, commits, commit graph, log outputs' ' |
| git init && |
| mkdir A A/B A/B/C && |
| test_commit c1 A/file1 && |
| test_commit c2 A/B/file2 && |
| test_commit c3 A/B/C/file3 && |
| test_commit c4 A/file1 && |
| test_commit c5 A/B/file2 && |
| test_commit c6 A/B/C/file3 && |
| test_commit c7 A/file1 && |
| test_commit c8 A/B/file2 && |
| test_commit c9 A/B/C/file3 && |
| test_commit c10 file_to_be_deleted && |
| git checkout -b side HEAD~4 && |
| test_commit side-1 file4 && |
| git checkout main && |
| git merge side && |
| test_commit c11 file5 && |
| mv file5 file5_renamed && |
| git add file5_renamed && |
| git commit -m "rename" && |
| rm file_to_be_deleted && |
| git add . && |
| git commit -m "file removed" && |
| git commit --allow-empty -m "empty" && |
| git commit-graph write --reachable --changed-paths && |
| |
| test_oid_cache <<-EOF |
| oid_version sha1:1 |
| oid_version sha256:2 |
| EOF |
| ' |
| |
| graph_read_expect () { |
| NUM_CHUNKS=6 |
| cat >expect <<- EOF |
| header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0 |
| num_commits: $1 |
| chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data |
| options: bloom(1,10,7) read_generation_data |
| EOF |
| test-tool read-graph >actual && |
| test_cmp expect actual |
| } |
| |
| test_expect_success 'commit-graph write wrote out the bloom chunks' ' |
| graph_read_expect 16 |
| ' |
| |
| # Turn off any inherited trace2 settings for this test. |
| sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT |
| sane_unset GIT_TRACE2_PERF_BRIEF |
| sane_unset GIT_TRACE2_CONFIG_PARAMS |
| |
| setup () { |
| rm -f "$TRASH_DIRECTORY/trace.perf" && |
| git -c core.commitGraph=false log --pretty="format:%s" $1 >log_wo_bloom && |
| GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.perf" git -c core.commitGraph=true log --pretty="format:%s" $1 >log_w_bloom |
| } |
| |
| test_bloom_filters_used () { |
| log_args=$1 |
| bloom_trace_prefix="statistics:{\"filter_not_present\":${2:-0},\"maybe\"" |
| setup "$log_args" && |
| grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" && |
| test_cmp log_wo_bloom log_w_bloom && |
| test_path_is_file "$TRASH_DIRECTORY/trace.perf" |
| } |
| |
| test_bloom_filters_not_used () { |
| log_args=$1 |
| setup "$log_args" && |
| |
| if grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf" |
| then |
| # if the Bloom filter system is initialized, ensure that no |
| # filters were used |
| data="statistics:{" |
| # unusable filters (e.g., those computed with a |
| # different value of commitGraph.changedPathsVersion) |
| # are counted in the filter_not_present bucket, so any |
| # value is OK there. |
| data="$data\"filter_not_present\":[0-9][0-9]*," |
| data="$data\"maybe\":0," |
| data="$data\"definitely_not\":0," |
| data="$data\"false_positive\":0}" |
| |
| grep -q "$data" "$TRASH_DIRECTORY/trace.perf" |
| fi && |
| test_cmp log_wo_bloom log_w_bloom |
| } |
| |
| for path in A A/B A/B/C A/file1 A/B/file2 A/B/C/file3 file4 file5 file5_renamed file_to_be_deleted |
| do |
| for option in "" \ |
| "--all" \ |
| "--full-history" \ |
| "--full-history --simplify-merges" \ |
| "--simplify-merges" \ |
| "--simplify-by-decoration" \ |
| "--follow" \ |
| "--first-parent" \ |
| "--topo-order" \ |
| "--date-order" \ |
| "--author-date-order" \ |
| "--ancestry-path side..main" |
| do |
| test_expect_success "git log option: $option for path: $path" ' |
| test_bloom_filters_used "$option -- $path" && |
| test_config commitgraph.readChangedPaths false && |
| test_bloom_filters_not_used "$option -- $path" |
| ' |
| done |
| done |
| |
| test_expect_success 'git log -- folder works with and without the trailing slash' ' |
| test_bloom_filters_used "-- A" && |
| test_bloom_filters_used "-- A/" |
| ' |
| |
| test_expect_success 'git log for path that does not exist. ' ' |
| test_bloom_filters_used "-- path_does_not_exist" |
| ' |
| |
| test_expect_success 'git log with --walk-reflogs does not use Bloom filters' ' |
| test_bloom_filters_not_used "--walk-reflogs -- A" |
| ' |
| |
| test_expect_success 'git log -- multiple path specs does not use Bloom filters' ' |
| test_bloom_filters_not_used "-- file4 A/file1" |
| ' |
| |
| test_expect_success 'git log -- "." pathspec at root does not use Bloom filters' ' |
| test_bloom_filters_not_used "-- ." |
| ' |
| |
| test_expect_success 'git log with wildcard that resolves to a single path uses Bloom filters' ' |
| test_bloom_filters_used "-- *4" && |
| test_bloom_filters_used "-- *renamed" |
| ' |
| |
| test_expect_success 'git log with wildcard that resolves to a multiple paths does not uses Bloom filters' ' |
| test_bloom_filters_not_used "-- *" && |
| test_bloom_filters_not_used "-- file*" |
| ' |
| |
| test_expect_success 'setup - add commit-graph to the chain without Bloom filters' ' |
| test_commit c14 A/anotherFile2 && |
| test_commit c15 A/B/anotherFile2 && |
| test_commit c16 A/B/C/anotherFile2 && |
| git commit-graph write --reachable --split --no-changed-paths && |
| test_line_count = 2 .git/objects/info/commit-graphs/commit-graph-chain |
| ' |
| |
| test_expect_success 'use Bloom filters even if the latest graph does not have Bloom filters' ' |
| # Ensure that the number of empty filters is equal to the number of |
| # filters in the latest graph layer to prove that they are loaded (and |
| # ignored). |
| test_bloom_filters_used "-- A/B" 3 |
| ' |
| |
| test_expect_success 'setup - add commit-graph to the chain with Bloom filters' ' |
| test_commit c17 A/anotherFile3 && |
| git commit-graph write --reachable --changed-paths --split && |
| test_line_count = 3 .git/objects/info/commit-graphs/commit-graph-chain |
| ' |
| |
| test_bloom_filters_used_when_some_filters_are_missing () { |
| log_args=$1 |
| bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":10" |
| setup "$log_args" && |
| grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" && |
| test_cmp log_wo_bloom log_w_bloom |
| } |
| |
| test_expect_success 'Use Bloom filters if they exist in the latest but not all commit graphs in the chain.' ' |
| test_bloom_filters_used_when_some_filters_are_missing "-- A/B" |
| ' |
| |
| test_expect_success 'persist filter settings' ' |
| test_when_finished rm -rf .git/objects/info/commit-graph* && |
| rm -rf .git/objects/info/commit-graph* && |
| GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ |
| GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=9 \ |
| GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY=15 \ |
| git commit-graph write --reachable --changed-paths && |
| grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15,\"max_changed_paths\":512" trace2.txt && |
| GIT_TRACE2_EVENT="$(pwd)/trace2-auto.txt" \ |
| git commit-graph write --reachable --changed-paths && |
| grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15,\"max_changed_paths\":512" trace2-auto.txt |
| ' |
| |
| test_max_changed_paths () { |
| grep "\"max_changed_paths\":$1" $2 |
| } |
| |
| test_filter_not_computed () { |
| grep "\"key\":\"filter-not-computed\",\"value\":\"$1\"" $2 |
| } |
| |
| test_filter_computed () { |
| grep "\"key\":\"filter-computed\",\"value\":\"$1\"" $2 |
| } |
| |
| test_filter_trunc_empty () { |
| grep "\"key\":\"filter-trunc-empty\",\"value\":\"$1\"" $2 |
| } |
| |
| test_filter_trunc_large () { |
| grep "\"key\":\"filter-trunc-large\",\"value\":\"$1\"" $2 |
| } |
| |
| test_filter_upgraded () { |
| grep "\"key\":\"filter-upgraded\",\"value\":\"$1\"" $2 |
| } |
| |
| test_expect_success 'correctly report changes over limit' ' |
| git init limits && |
| ( |
| cd limits && |
| mkdir d && |
| mkdir d/e && |
| |
| for i in $(test_seq 1 2) |
| do |
| printf $i >d/file$i.txt && |
| printf $i >d/e/file$i.txt || return 1 |
| done && |
| |
| mkdir mode && |
| printf bash >mode/script.sh && |
| |
| mkdir foo && |
| touch foo/bar && |
| touch foo.txt && |
| |
| git add d foo foo.txt mode && |
| git commit -m "files" && |
| |
| # Commit has 7 file and 4 directory adds |
| GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=10 \ |
| GIT_TRACE2_EVENT="$(pwd)/trace" \ |
| git commit-graph write --reachable --changed-paths && |
| test_max_changed_paths 10 trace && |
| test_filter_computed 1 trace && |
| test_filter_trunc_large 1 trace && |
| |
| for path in $(git ls-tree -r --name-only HEAD) |
| do |
| git -c commitGraph.readChangedPaths=false log \ |
| -- $path >expect && |
| git log -- $path >actual && |
| test_cmp expect actual || return 1 |
| done && |
| |
| # Make a variety of path changes |
| printf new1 >d/e/file1.txt && |
| printf new2 >d/file2.txt && |
| rm d/e/file2.txt && |
| rm -r foo && |
| printf text >foo && |
| mkdir f && |
| printf new1 >f/file1.txt && |
| |
| # including a mode-only change (counts as modified) |
| git update-index --chmod=+x mode/script.sh && |
| |
| git add foo d f && |
| git commit -m "complicated" && |
| |
| # start from scratch and rebuild |
| rm -f .git/objects/info/commit-graph && |
| GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=10 \ |
| GIT_TRACE2_EVENT="$(pwd)/trace-edit" \ |
| git commit-graph write --reachable --changed-paths && |
| test_max_changed_paths 10 trace-edit && |
| test_filter_computed 2 trace-edit && |
| test_filter_trunc_large 2 trace-edit && |
| |
| for path in $(git ls-tree -r --name-only HEAD) |
| do |
| git -c commitGraph.readChangedPaths=false log \ |
| -- $path >expect && |
| git log -- $path >actual && |
| test_cmp expect actual || return 1 |
| done && |
| |
| # start from scratch and rebuild |
| rm -f .git/objects/info/commit-graph && |
| GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=11 \ |
| GIT_TRACE2_EVENT="$(pwd)/trace-update" \ |
| git commit-graph write --reachable --changed-paths && |
| test_max_changed_paths 11 trace-update && |
| test_filter_computed 2 trace-update && |
| test_filter_trunc_large 0 trace-update && |
| |
| for path in $(git ls-tree -r --name-only HEAD) |
| do |
| git -c commitGraph.readChangedPaths=false log \ |
| -- $path >expect && |
| git log -- $path >actual && |
| test_cmp expect actual || return 1 |
| done |
| ) |
| ' |
| |
| test_expect_success 'correctly report commits with no changed paths' ' |
| git init empty && |
| test_when_finished "rm -fr empty" && |
| ( |
| cd empty && |
| |
| git commit --allow-empty -m "initial commit" && |
| |
| GIT_TRACE2_EVENT="$(pwd)/trace.event" \ |
| git commit-graph write --reachable --changed-paths && |
| test_filter_computed 1 trace.event && |
| test_filter_not_computed 0 trace.event && |
| test_filter_trunc_empty 1 trace.event && |
| test_filter_trunc_large 0 trace.event |
| ) |
| ' |
| |
| test_expect_success 'Bloom generation is limited by --max-new-filters' ' |
| ( |
| cd limits && |
| test_commit c2 filter && |
| test_commit c3 filter && |
| test_commit c4 no-filter && |
| |
| rm -f trace.event && |
| GIT_TRACE2_EVENT="$(pwd)/trace.event" \ |
| git commit-graph write --reachable --split=replace \ |
| --changed-paths --max-new-filters=2 && |
| |
| test_filter_computed 2 trace.event && |
| test_filter_not_computed 3 trace.event && |
| test_filter_trunc_empty 0 trace.event && |
| test_filter_trunc_large 0 trace.event |
| ) |
| ' |
| |
| test_expect_success 'Bloom generation backfills previously-skipped filters' ' |
| # Check specifying commitGraph.maxNewFilters over "git config" works. |
| test_config -C limits commitGraph.maxNewFilters 1 && |
| ( |
| cd limits && |
| |
| rm -f trace.event && |
| GIT_TRACE2_EVENT="$(pwd)/trace.event" \ |
| git commit-graph write --reachable --changed-paths \ |
| --split=replace && |
| test_filter_computed 1 trace.event && |
| test_filter_not_computed 4 trace.event && |
| test_filter_trunc_empty 0 trace.event && |
| test_filter_trunc_large 0 trace.event |
| ) |
| ' |
| |
| test_expect_success '--max-new-filters overrides configuration' ' |
| git init override && |
| test_when_finished "rm -fr override" && |
| test_config -C override commitGraph.maxNewFilters 2 && |
| ( |
| cd override && |
| test_commit one && |
| test_commit two && |
| |
| rm -f trace.event && |
| GIT_TRACE2_EVENT="$(pwd)/trace.event" \ |
| git commit-graph write --reachable --changed-paths \ |
| --max-new-filters=1 && |
| test_filter_computed 1 trace.event && |
| test_filter_not_computed 1 trace.event && |
| test_filter_trunc_empty 0 trace.event && |
| test_filter_trunc_large 0 trace.event |
| ) |
| ' |
| |
| test_expect_success 'Bloom generation backfills empty commits' ' |
| git init empty && |
| test_when_finished "rm -fr empty" && |
| ( |
| cd empty && |
| for i in $(test_seq 1 6) |
| do |
| git commit --allow-empty -m "$i" || return 1 |
| done && |
| |
| # Generate Bloom filters for empty commits 1-6, two at a time. |
| for i in $(test_seq 1 3) |
| do |
| rm -f trace.event && |
| GIT_TRACE2_EVENT="$(pwd)/trace.event" \ |
| git commit-graph write --reachable \ |
| --changed-paths --max-new-filters=2 && |
| test_filter_computed 2 trace.event && |
| test_filter_not_computed 4 trace.event && |
| test_filter_trunc_empty 2 trace.event && |
| test_filter_trunc_large 0 trace.event || return 1 |
| done && |
| |
| # Finally, make sure that once all commits have filters, that |
| # none are subsequently recomputed. |
| rm -f trace.event && |
| GIT_TRACE2_EVENT="$(pwd)/trace.event" \ |
| git commit-graph write --reachable \ |
| --changed-paths --max-new-filters=2 && |
| test_filter_computed 0 trace.event && |
| test_filter_not_computed 6 trace.event && |
| test_filter_trunc_empty 0 trace.event && |
| test_filter_trunc_large 0 trace.event |
| ) |
| ' |
| |
| graph=.git/objects/info/commit-graph |
| graphdir=.git/objects/info/commit-graphs |
| chain=$graphdir/commit-graph-chain |
| |
| test_expect_success 'setup for mixed Bloom setting tests' ' |
| repo=mixed-bloom-settings && |
| |
| git init $repo && |
| for i in one two three |
| do |
| test_commit -C $repo $i file || return 1 |
| done |
| ' |
| |
| test_expect_success 'ensure Bloom filters with incompatible settings are ignored' ' |
| # Compute Bloom filters with "unusual" settings. |
| git -C $repo rev-parse one >in && |
| GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=3 git -C $repo commit-graph write \ |
| --stdin-commits --changed-paths --split <in && |
| layer=$(head -n 1 $repo/$chain) && |
| |
| # A commit-graph layer without Bloom filters "hides" the layers |
| # below ... |
| git -C $repo rev-parse two >in && |
| git -C $repo commit-graph write --stdin-commits --no-changed-paths \ |
| --split=no-merge <in && |
| |
| # Another commit-graph layer that has Bloom filters, but with |
| # standard settings, and is thus incompatible with the base |
| # layer written above. |
| git -C $repo rev-parse HEAD >in && |
| git -C $repo commit-graph write --stdin-commits --changed-paths \ |
| --split=no-merge <in && |
| |
| test_line_count = 3 $repo/$chain && |
| |
| # Ensure that incompatible Bloom filters are ignored. |
| git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- file \ |
| >expect 2>err && |
| git -C $repo log --oneline --no-decorate -- file >actual 2>err && |
| test_cmp expect actual && |
| grep "disabling Bloom filters for commit-graph layer .$layer." err |
| ' |
| |
| test_expect_success 'merge graph layers with incompatible Bloom settings' ' |
| # Ensure that incompatible Bloom filters are ignored when |
| # merging existing layers. |
| >trace2.txt && |
| GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ |
| git -C $repo commit-graph write --reachable --changed-paths 2>err && |
| grep "disabling Bloom filters for commit-graph layer .$layer." err && |
| grep "{\"hash_version\":1,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt && |
| |
| test_path_is_file $repo/$graph && |
| test_dir_is_empty $repo/$graphdir && |
| |
| git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- \ |
| file >expect && |
| trace_out="$(pwd)/trace.perf" && |
| GIT_TRACE2_PERF="$trace_out" \ |
| git -C $repo log --oneline --no-decorate -- file >actual 2>err && |
| |
| test_cmp expect actual && |
| grep "statistics:{\"filter_not_present\":0," trace.perf && |
| test_must_be_empty err |
| ' |
| |
| # chosen to be the same under all Unicode normalization forms |
| CENT=$(printf "\302\242") |
| |
| test_expect_success 'ensure Bloom filter with incompatible versions are ignored' ' |
| rm "$repo/$graph" && |
| |
| git -C $repo log --oneline --no-decorate -- $CENT >expect && |
| |
| # Compute v1 Bloom filters for commits at the bottom. |
| git -C $repo rev-parse HEAD^ >in && |
| git -C $repo commit-graph write --stdin-commits --changed-paths \ |
| --split <in && |
| |
| # Compute v2 Bloomfilters for the rest of the commits at the top. |
| git -C $repo rev-parse HEAD >in && |
| git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write \ |
| --stdin-commits --changed-paths --split=no-merge <in && |
| |
| test_line_count = 2 $repo/$chain && |
| |
| git -C $repo log --oneline --no-decorate -- $CENT >actual 2>err && |
| test_cmp expect actual && |
| |
| layer="$(head -n 1 $repo/$chain)" && |
| cat >expect.err <<-EOF && |
| warning: disabling Bloom filters for commit-graph layer $SQ$layer$SQ due to incompatible settings |
| EOF |
| test_cmp expect.err err && |
| |
| # Merge the two layers with incompatible bloom filter versions, |
| # ensuring that the v2 filters are used. |
| >trace2.txt && |
| GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ |
| git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write --reachable --changed-paths 2>err && |
| grep "disabling Bloom filters for commit-graph layer .$layer." err && |
| grep "{\"hash_version\":2,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt |
| ' |
| |
| get_first_changed_path_filter () { |
| test-tool read-graph bloom-filters >filters.dat && |
| head -n 1 filters.dat |
| } |
| |
| test_expect_success 'set up repo with high bit path, version 1 changed-path' ' |
| git init highbit1 && |
| test_commit -C highbit1 c1 "$CENT" && |
| git -C highbit1 commit-graph write --reachable --changed-paths |
| ' |
| |
| test_expect_success 'setup check value of version 1 changed-path' ' |
| ( |
| cd highbit1 && |
| echo "52a9" >expect && |
| get_first_changed_path_filter >actual |
| ) |
| ' |
| |
| # expect will not match actual if char is unsigned by default. Write the test |
| # in this way, so that a user running this test script can still see if the two |
| # files match. (It will appear as an ordinary success if they match, and a skip |
| # if not.) |
| if test_cmp highbit1/expect highbit1/actual |
| then |
| test_set_prereq SIGNED_CHAR_BY_DEFAULT |
| fi |
| test_expect_success SIGNED_CHAR_BY_DEFAULT 'check value of version 1 changed-path' ' |
| # Only the prereq matters for this test. |
| true |
| ' |
| |
| test_expect_success 'setup make another commit' ' |
| # "git log" does not use Bloom filters for root commits - see how, in |
| # revision.c, rev_compare_tree() (the only code path that eventually calls |
| # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit |
| # has one parent. Therefore, make another commit so that we perform the tests on |
| # a non-root commit. |
| test_commit -C highbit1 anotherc1 "another$CENT" |
| ' |
| |
| test_expect_success 'version 1 changed-path used when version 1 requested' ' |
| ( |
| cd highbit1 && |
| test_bloom_filters_used "-- another$CENT" |
| ) |
| ' |
| |
| test_expect_success 'version 1 changed-path not used when version 2 requested' ' |
| ( |
| cd highbit1 && |
| git config --add commitGraph.changedPathsVersion 2 && |
| test_bloom_filters_not_used "-- another$CENT" |
| ) |
| ' |
| |
| test_expect_success 'version 1 changed-path used when autodetect requested' ' |
| ( |
| cd highbit1 && |
| git config --add commitGraph.changedPathsVersion -1 && |
| test_bloom_filters_used "-- another$CENT" |
| ) |
| ' |
| |
| test_expect_success 'when writing another commit graph, preserve existing version 1 of changed-path' ' |
| test_commit -C highbit1 c1double "$CENT$CENT" && |
| git -C highbit1 commit-graph write --reachable --changed-paths && |
| ( |
| cd highbit1 && |
| git config --add commitGraph.changedPathsVersion -1 && |
| echo "options: bloom(1,10,7) read_generation_data" >expect && |
| test-tool read-graph >full && |
| grep options full >actual && |
| test_cmp expect actual |
| ) |
| ' |
| |
| test_expect_success 'set up repo with high bit path, version 2 changed-path' ' |
| git init highbit2 && |
| git -C highbit2 config --add commitGraph.changedPathsVersion 2 && |
| test_commit -C highbit2 c2 "$CENT" && |
| git -C highbit2 commit-graph write --reachable --changed-paths |
| ' |
| |
| test_expect_success 'check value of version 2 changed-path' ' |
| ( |
| cd highbit2 && |
| echo "c01f" >expect && |
| get_first_changed_path_filter >actual && |
| test_cmp expect actual |
| ) |
| ' |
| |
| test_expect_success 'setup make another commit' ' |
| # "git log" does not use Bloom filters for root commits - see how, in |
| # revision.c, rev_compare_tree() (the only code path that eventually calls |
| # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit |
| # has one parent. Therefore, make another commit so that we perform the tests on |
| # a non-root commit. |
| test_commit -C highbit2 anotherc2 "another$CENT" |
| ' |
| |
| test_expect_success 'version 2 changed-path used when version 2 requested' ' |
| ( |
| cd highbit2 && |
| test_bloom_filters_used "-- another$CENT" |
| ) |
| ' |
| |
| test_expect_success 'version 2 changed-path not used when version 1 requested' ' |
| ( |
| cd highbit2 && |
| git config --add commitGraph.changedPathsVersion 1 && |
| test_bloom_filters_not_used "-- another$CENT" |
| ) |
| ' |
| |
| test_expect_success 'version 2 changed-path used when autodetect requested' ' |
| ( |
| cd highbit2 && |
| git config --add commitGraph.changedPathsVersion -1 && |
| test_bloom_filters_used "-- another$CENT" |
| ) |
| ' |
| |
| test_expect_success 'when writing another commit graph, preserve existing version 2 of changed-path' ' |
| test_commit -C highbit2 c2double "$CENT$CENT" && |
| git -C highbit2 commit-graph write --reachable --changed-paths && |
| ( |
| cd highbit2 && |
| git config --add commitGraph.changedPathsVersion -1 && |
| echo "options: bloom(2,10,7) read_generation_data" >expect && |
| test-tool read-graph >full && |
| grep options full >actual && |
| test_cmp expect actual |
| ) |
| ' |
| |
| test_expect_success 'when writing commit graph, do not reuse changed-path of another version' ' |
| git init doublewrite && |
| test_commit -C doublewrite c "$CENT" && |
| |
| git -C doublewrite config --add commitGraph.changedPathsVersion 1 && |
| >trace2.txt && |
| GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ |
| git -C doublewrite commit-graph write --reachable --changed-paths && |
| test_filter_computed 1 trace2.txt && |
| test_filter_upgraded 0 trace2.txt && |
| |
| git -C doublewrite commit-graph write --reachable --changed-paths && |
| for v in -2 3 |
| do |
| git -C doublewrite config --add commitGraph.changedPathsVersion $v && |
| git -C doublewrite commit-graph write --reachable --changed-paths 2>err && |
| cat >expect <<-EOF && |
| warning: attempting to write a commit-graph, but ${SQ}commitGraph.changedPathsVersion${SQ} ($v) is not supported |
| EOF |
| test_cmp expect err || return 1 |
| done && |
| |
| git -C doublewrite config --add commitGraph.changedPathsVersion 2 && |
| >trace2.txt && |
| GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ |
| git -C doublewrite commit-graph write --reachable --changed-paths && |
| test_filter_computed 1 trace2.txt && |
| test_filter_upgraded 0 trace2.txt && |
| |
| ( |
| cd doublewrite && |
| echo "c01f" >expect && |
| get_first_changed_path_filter >actual && |
| test_cmp expect actual |
| ) |
| ' |
| |
| test_expect_success 'when writing commit graph, reuse changed-path of another version where possible' ' |
| git init upgrade && |
| |
| test_commit -C upgrade base no-high-bits && |
| |
| git -C upgrade config --add commitGraph.changedPathsVersion 1 && |
| >trace2.txt && |
| GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ |
| git -C upgrade commit-graph write --reachable --changed-paths && |
| test_filter_computed 1 trace2.txt && |
| test_filter_upgraded 0 trace2.txt && |
| |
| git -C upgrade config --add commitGraph.changedPathsVersion 2 && |
| >trace2.txt && |
| GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ |
| git -C upgrade commit-graph write --reachable --changed-paths && |
| test_filter_computed 0 trace2.txt && |
| test_filter_upgraded 1 trace2.txt |
| ' |
| |
| corrupt_graph () { |
| test_when_finished "rm -rf $graph" && |
| git commit-graph write --reachable --changed-paths && |
| corrupt_chunk_file $graph "$@" |
| } |
| |
| check_corrupt_graph () { |
| corrupt_graph "$@" && |
| git -c core.commitGraph=false log -- A/B/file2 >expect.out && |
| git -c core.commitGraph=true log -- A/B/file2 >out 2>err && |
| test_cmp expect.out out |
| } |
| |
| test_expect_success 'Bloom reader notices too-small data chunk' ' |
| check_corrupt_graph BDAT clear 00000000 && |
| echo "warning: ignoring too-small changed-path chunk" \ |
| "(4 < 12) in commit-graph file" >expect.err && |
| test_cmp expect.err err |
| ' |
| |
| test_expect_success 'Bloom reader notices out-of-bounds filter offsets' ' |
| check_corrupt_graph BIDX 12 FFFFFFFF && |
| # use grep to avoid depending on exact chunk size |
| grep "warning: ignoring out-of-range offset (4294967295) for changed-path filter at pos 3 of .git/objects/info/commit-graph" err |
| ' |
| |
| test_expect_success 'Bloom reader notices too-small index chunk' ' |
| # replace the index with a single entry, making most |
| # lookups out-of-bounds |
| check_corrupt_graph BIDX clear 00000000 && |
| echo "warning: commit-graph changed-path index chunk" \ |
| "is too small" >expect.err && |
| test_cmp expect.err err |
| ' |
| |
| test_expect_success 'Bloom reader notices out-of-order index offsets' ' |
| # we do not know any real offsets, but we can pick |
| # something plausible; we should not get to the point of |
| # actually reading from the bogus offsets anyway. |
| corrupt_graph BIDX 4 0000000c00000005 && |
| echo "warning: ignoring decreasing changed-path index offsets" \ |
| "(12 > 5) for positions 1 and 2 of .git/objects/info/commit-graph" >expect.err && |
| git -c core.commitGraph=false log -- A/B/file2 >expect.out && |
| git -c core.commitGraph=true log -- A/B/file2 >out 2>err && |
| test_cmp expect.out out && |
| test_cmp expect.err err |
| ' |
| |
| test_done |