| #!/bin/sh |
| |
| test_description='direct path-walk API tests' |
| |
| . ./test-lib.sh |
| |
| test_expect_success 'setup test repository' ' |
| git checkout -b base && |
| |
| # Create tree objects that are only reachable via tags, |
| # not from any commit in the history. |
| child_blob_oid=$(echo "child blob content" | git hash-object -t blob -w --stdin) && |
| child_tree_oid=$(printf "100644 blob %s\tfile\n" "$child_blob_oid" | git mktree) && |
| tree_tag_oid=$(printf "040000 tree %s\tchild\n" "$child_tree_oid" | git mktree) && |
| git tag -a -m "tree" tree-tag "$tree_tag_oid" && |
| file2_blob_oid=$(echo "tagged tree file2" | git hash-object -t blob -w --stdin) && |
| tree_tag2_oid=$(printf "040000 tree %s\tchild\n100644 blob %s\tfile2\n" "$child_tree_oid" "$file2_blob_oid" | git mktree) && |
| git tag tree-tag2 "$tree_tag2_oid" && |
| |
| echo blob >file && |
| blob_oid=$(git hash-object -t blob -w --stdin <file) && |
| git tag -a -m "blob" blob-tag "$blob_oid" && |
| echo blob2 >file2 && |
| blob2_oid=$(git hash-object -t blob -w --stdin <file2) && |
| git tag blob-tag2 "$blob2_oid" && |
| |
| rm -fr file file2 && |
| |
| mkdir left && |
| mkdir right && |
| echo a >a && |
| echo b >left/b && |
| echo c >right/c && |
| git add . && |
| git commit -m "first" && |
| git tag -m "first" first HEAD && |
| |
| echo d >right/d && |
| git add right && |
| git commit -m "second" && |
| git tag -a -m "second (under)" second.1 HEAD && |
| git tag -a -m "second (top)" second.2 second.1 && |
| |
| # Set up file/dir collision in history. |
| rm a && |
| mkdir a && |
| echo a >a/a && |
| echo bb >left/b && |
| git add a left && |
| git commit -m "third" && |
| git tag -a -m "third" third && |
| |
| git checkout -b topic HEAD~1 && |
| echo cc >right/c && |
| git commit -a -m "topic" && |
| git tag -a -m "fourth" fourth |
| ' |
| |
| test_expect_success 'all' ' |
| test-tool path-walk -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tag:/tags:$(git rev-parse refs/tags/first) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 1:tag:/tags:$(git rev-parse refs/tags/third) |
| 1:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree::$(git rev-parse topic^{tree}) |
| 3:tree::$(git rev-parse base^{tree}) |
| 3:tree::$(git rev-parse base~1^{tree}) |
| 3:tree::$(git rev-parse base~2^{tree}) |
| 4:blob:a:$(git rev-parse base~2:a) |
| 5:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{}) |
| 5:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2^{}) |
| 6:blob:file2:$(git rev-parse refs/tags/tree-tag2^{}:file2) |
| 7:tree:a/:$(git rev-parse base:a) |
| 8:tree:child/:$(git rev-parse refs/tags/tree-tag:child) |
| 9:blob:child/file:$(git rev-parse refs/tags/tree-tag:child/file) |
| 10:tree:left/:$(git rev-parse base:left) |
| 10:tree:left/:$(git rev-parse base~2:left) |
| 11:blob:left/b:$(git rev-parse base~2:left/b) |
| 11:blob:left/b:$(git rev-parse base:left/b) |
| 12:tree:right/:$(git rev-parse topic:right) |
| 12:tree:right/:$(git rev-parse base~1:right) |
| 12:tree:right/:$(git rev-parse base~2:right) |
| 13:blob:right/c:$(git rev-parse base~2:right/c) |
| 13:blob:right/c:$(git rev-parse topic:right/c) |
| 14:blob:right/d:$(git rev-parse base~1:right/d) |
| blobs:10 |
| commits:4 |
| tags:7 |
| trees:13 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'indexed objects' ' |
| test_when_finished git reset --hard && |
| |
| # stage change into index, adding a blob but |
| # also invalidating the cache-tree for the root |
| # and the "left" directory. |
| echo bogus >left/c && |
| git add left && |
| |
| test-tool path-walk -- --indexed-objects >out && |
| |
| cat >expect <<-EOF && |
| 0:blob:a:$(git rev-parse HEAD:a) |
| 1:blob:left/b:$(git rev-parse HEAD:left/b) |
| 2:blob:left/c:$(git rev-parse :left/c) |
| 3:blob:right/c:$(git rev-parse HEAD:right/c) |
| 4:blob:right/d:$(git rev-parse HEAD:right/d) |
| 5:tree:right/:$(git rev-parse topic:right) |
| blobs:5 |
| commits:0 |
| tags:0 |
| trees:1 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'branches and indexed objects mix well' ' |
| test_when_finished git reset --hard && |
| |
| # stage change into index, adding a blob but |
| # also invalidating the cache-tree for the root |
| # and the "right" directory. |
| echo fake >right/d && |
| git add right && |
| |
| test-tool path-walk -- --indexed-objects --branches >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}) |
| 1:tree::$(git rev-parse base~2^{tree}) |
| 2:tree:a/:$(git rev-parse refs/tags/third:a) |
| 3:tree:left/:$(git rev-parse base:left) |
| 3:tree:left/:$(git rev-parse base~2:left) |
| 4:blob:left/b:$(git rev-parse base:left/b) |
| 4:blob:left/b:$(git rev-parse base~2:left/b) |
| 5:tree:right/:$(git rev-parse topic:right) |
| 5:tree:right/:$(git rev-parse base~1:right) |
| 5:tree:right/:$(git rev-parse base~2:right) |
| 6:blob:right/c:$(git rev-parse base~2:right/c) |
| 6:blob:right/c:$(git rev-parse topic:right/c) |
| 7:blob:right/d:$(git rev-parse base~1:right/d) |
| 7:blob:right/d:$(git rev-parse :right/d) |
| 8:blob:a:$(git rev-parse base~2:a) |
| blobs:7 |
| commits:4 |
| tags:0 |
| trees:10 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'base & topic, sparse' ' |
| cat >patterns <<-EOF && |
| /* |
| !/*/ |
| /left/ |
| EOF |
| |
| test-tool path-walk --stdin-pl -- base topic <patterns >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}) |
| 1:tree::$(git rev-parse base~2^{tree}) |
| 2:blob:a:$(git rev-parse base~2:a) |
| 3:tree:left/:$(git rev-parse base:left) |
| 3:tree:left/:$(git rev-parse base~2:left) |
| 4:blob:left/b:$(git rev-parse base~2:left/b) |
| 4:blob:left/b:$(git rev-parse base:left/b) |
| blobs:3 |
| commits:4 |
| tags:0 |
| trees:6 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'base & topic, sparse, no tree pruning' ' |
| cat >patterns <<-EOF && |
| /* |
| !/*/ |
| /left/ |
| EOF |
| |
| test-tool path-walk --stdin-pl --no-pl-sparse-trees \ |
| -- base topic <patterns >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}) |
| 1:tree::$(git rev-parse base~2^{tree}) |
| 2:blob:a:$(git rev-parse base~2:a) |
| 3:tree:a/:$(git rev-parse base:a) |
| 4:tree:left/:$(git rev-parse base:left) |
| 4:tree:left/:$(git rev-parse base~2:left) |
| 5:blob:left/b:$(git rev-parse base~2:left/b) |
| 5:blob:left/b:$(git rev-parse base:left/b) |
| 6:tree:right/:$(git rev-parse topic:right) |
| 6:tree:right/:$(git rev-parse base~1:right) |
| 6:tree:right/:$(git rev-parse base~2:right) |
| blobs:3 |
| commits:4 |
| tags:0 |
| trees:10 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic only' ' |
| test-tool path-walk -- topic >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}) |
| 1:tree::$(git rev-parse base~2^{tree}) |
| 2:blob:a:$(git rev-parse base~2:a) |
| 3:tree:left/:$(git rev-parse base~2:left) |
| 4:blob:left/b:$(git rev-parse base~2:left/b) |
| 5:tree:right/:$(git rev-parse topic:right) |
| 5:tree:right/:$(git rev-parse base~1:right) |
| 5:tree:right/:$(git rev-parse base~2:right) |
| 6:blob:right/c:$(git rev-parse base~2:right/c) |
| 6:blob:right/c:$(git rev-parse topic:right/c) |
| 7:blob:right/d:$(git rev-parse base~1:right/d) |
| blobs:5 |
| commits:3 |
| tags:0 |
| trees:7 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic, not base' ' |
| test-tool path-walk -- topic --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 2:blob:a:$(git rev-parse topic:a):UNINTERESTING |
| 3:tree:left/:$(git rev-parse topic:left):UNINTERESTING |
| 4:blob:left/b:$(git rev-parse topic:left/b):UNINTERESTING |
| 5:tree:right/:$(git rev-parse topic:right) |
| 6:blob:right/c:$(git rev-parse topic:right/c) |
| 7:blob:right/d:$(git rev-parse topic:right/d):UNINTERESTING |
| blobs:4 |
| commits:1 |
| tags:0 |
| trees:3 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'fourth, blob-tag2, not base' ' |
| test-tool path-walk -- fourth blob-tag2 --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 1:tag:/tags:$(git rev-parse fourth) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree::$(git rev-parse topic^{tree}) |
| 4:blob:a:$(git rev-parse base~1:a):UNINTERESTING |
| 5:tree:left/:$(git rev-parse base~1:left):UNINTERESTING |
| 6:blob:left/b:$(git rev-parse base~1:left/b):UNINTERESTING |
| 7:tree:right/:$(git rev-parse topic:right) |
| 8:blob:right/c:$(git rev-parse topic:right/c) |
| 9:blob:right/d:$(git rev-parse base~1:right/d):UNINTERESTING |
| blobs:5 |
| commits:1 |
| tags:1 |
| trees:3 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic, not base, only blobs' ' |
| test-tool path-walk --no-trees --no-commits \ |
| -- topic --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:blob:a:$(git rev-parse topic:a):UNINTERESTING |
| 1:blob:left/b:$(git rev-parse topic:left/b):UNINTERESTING |
| 2:blob:right/c:$(git rev-parse topic:right/c) |
| 3:blob:right/d:$(git rev-parse topic:right/d):UNINTERESTING |
| blobs:4 |
| commits:0 |
| tags:0 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| # No, this doesn't make a lot of sense for the path-walk API, |
| # but it is possible to do. |
| test_expect_success 'topic, not base, only commits' ' |
| test-tool path-walk --no-blobs --no-trees \ |
| -- topic --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| commits:1 |
| blobs:0 |
| tags:0 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic, not base, only trees' ' |
| test-tool path-walk --no-blobs --no-commits \ |
| -- topic --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:tree::$(git rev-parse topic^{tree}) |
| 1:tree:left/:$(git rev-parse topic:left):UNINTERESTING |
| 2:tree:right/:$(git rev-parse topic:right) |
| commits:0 |
| blobs:0 |
| tags:0 |
| trees:3 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic, not base, boundary' ' |
| test-tool path-walk -- --boundary topic --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base~1):UNINTERESTING |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}):UNINTERESTING |
| 2:blob:a:$(git rev-parse base~1:a):UNINTERESTING |
| 3:tree:left/:$(git rev-parse base~1:left):UNINTERESTING |
| 4:blob:left/b:$(git rev-parse base~1:left/b):UNINTERESTING |
| 5:tree:right/:$(git rev-parse topic:right) |
| 5:tree:right/:$(git rev-parse base~1:right):UNINTERESTING |
| 6:blob:right/c:$(git rev-parse base~1:right/c):UNINTERESTING |
| 6:blob:right/c:$(git rev-parse topic:right/c) |
| 7:blob:right/d:$(git rev-parse base~1:right/d):UNINTERESTING |
| blobs:5 |
| commits:2 |
| tags:0 |
| trees:5 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic, not base, boundary with pruning' ' |
| test-tool path-walk --prune -- --boundary topic --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base~1):UNINTERESTING |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}):UNINTERESTING |
| 2:tree:right/:$(git rev-parse topic:right) |
| 2:tree:right/:$(git rev-parse base~1:right):UNINTERESTING |
| 3:blob:right/c:$(git rev-parse base~1:right/c):UNINTERESTING |
| 3:blob:right/c:$(git rev-parse topic:right/c) |
| blobs:2 |
| commits:2 |
| tags:0 |
| trees:4 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic, not base, --edge-aggressive with pruning' ' |
| test-tool path-walk --prune --edge-aggressive -- topic --not base >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base^{tree}):UNINTERESTING |
| 2:tree:right/:$(git rev-parse topic:right) |
| 2:tree:right/:$(git rev-parse base:right):UNINTERESTING |
| 3:blob:right/c:$(git rev-parse base:right/c):UNINTERESTING |
| 3:blob:right/c:$(git rev-parse topic:right/c) |
| blobs:2 |
| commits:1 |
| tags:0 |
| trees:4 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'trees are reported exactly once' ' |
| test_when_finished "rm -rf unique-trees" && |
| test_create_repo unique-trees && |
| ( |
| cd unique-trees && |
| mkdir initial && |
| test_commit initial/file && |
| git switch -c move-to-top && |
| git mv initial/file.t ./ && |
| test_tick && |
| git commit -m moved && |
| git update-ref refs/heads/other HEAD |
| ) && |
| test-tool -C unique-trees path-walk -- --all >out && |
| tree=$(git -C unique-trees rev-parse HEAD:) && |
| grep "$tree" out >out-filtered && |
| test_line_count = 1 out-filtered |
| ' |
| |
| test_expect_success 'all, blob:none filter' ' |
| test-tool path-walk --filter=blob:none -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tag:/tags:$(git rev-parse refs/tags/first) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 1:tag:/tags:$(git rev-parse refs/tags/third) |
| 1:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree::$(git rev-parse topic^{tree}) |
| 3:tree::$(git rev-parse base^{tree}) |
| 3:tree::$(git rev-parse base~1^{tree}) |
| 3:tree::$(git rev-parse base~2^{tree}) |
| 4:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{}) |
| 4:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2^{}) |
| 5:tree:a/:$(git rev-parse base:a) |
| 6:tree:child/:$(git rev-parse refs/tags/tree-tag:child) |
| 7:tree:left/:$(git rev-parse base:left) |
| 7:tree:left/:$(git rev-parse base~2:left) |
| 8:tree:right/:$(git rev-parse topic:right) |
| 8:tree:right/:$(git rev-parse base~1:right) |
| 8:tree:right/:$(git rev-parse base~2:right) |
| blobs:2 |
| commits:4 |
| tags:7 |
| trees:13 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic only, blob:none filter' ' |
| test-tool path-walk --filter=blob:none -- topic >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}) |
| 1:tree::$(git rev-parse base~2^{tree}) |
| 2:tree:left/:$(git rev-parse base~2:left) |
| 3:tree:right/:$(git rev-parse topic:right) |
| 3:tree:right/:$(git rev-parse base~1:right) |
| 3:tree:right/:$(git rev-parse base~2:right) |
| blobs:0 |
| commits:3 |
| tags:0 |
| trees:7 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, blob:limit=0 filter' ' |
| test-tool path-walk --filter=blob:limit=0 -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tag:/tags:$(git rev-parse refs/tags/first) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 1:tag:/tags:$(git rev-parse refs/tags/third) |
| 1:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree::$(git rev-parse topic^{tree}) |
| 3:tree::$(git rev-parse base^{tree}) |
| 3:tree::$(git rev-parse base~1^{tree}) |
| 3:tree::$(git rev-parse base~2^{tree}) |
| 4:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{}) |
| 4:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2^{}) |
| 5:tree:a/:$(git rev-parse base:a) |
| 6:tree:child/:$(git rev-parse refs/tags/tree-tag:child) |
| 7:tree:left/:$(git rev-parse base:left) |
| 7:tree:left/:$(git rev-parse base~2:left) |
| 8:tree:right/:$(git rev-parse topic:right) |
| 8:tree:right/:$(git rev-parse base~1:right) |
| 8:tree:right/:$(git rev-parse base~2:right) |
| blobs:2 |
| commits:4 |
| tags:7 |
| trees:13 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, blob:limit=3 filter' ' |
| test-tool path-walk --filter=blob:limit=3 -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tag:/tags:$(git rev-parse refs/tags/first) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 1:tag:/tags:$(git rev-parse refs/tags/third) |
| 1:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree::$(git rev-parse topic^{tree}) |
| 3:tree::$(git rev-parse base^{tree}) |
| 3:tree::$(git rev-parse base~1^{tree}) |
| 3:tree::$(git rev-parse base~2^{tree}) |
| 4:blob:a:$(git rev-parse base~2:a) |
| 5:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{}) |
| 5:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2^{}) |
| 6:tree:a/:$(git rev-parse base:a) |
| 7:tree:child/:$(git rev-parse refs/tags/tree-tag:child) |
| 8:tree:left/:$(git rev-parse base:left) |
| 8:tree:left/:$(git rev-parse base~2:left) |
| 9:blob:left/b:$(git rev-parse base~2:left/b) |
| 10:tree:right/:$(git rev-parse topic:right) |
| 10:tree:right/:$(git rev-parse base~1:right) |
| 10:tree:right/:$(git rev-parse base~2:right) |
| 11:blob:right/c:$(git rev-parse base~2:right/c) |
| 12:blob:right/d:$(git rev-parse base~1:right/d) |
| blobs:6 |
| commits:4 |
| tags:7 |
| trees:13 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, tree:0 filter' ' |
| test-tool path-walk --filter=tree:0 -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tag:/tags:$(git rev-parse refs/tags/first) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 1:tag:/tags:$(git rev-parse refs/tags/third) |
| 1:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{tree}) |
| 3:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2) |
| blobs:2 |
| commits:4 |
| tags:7 |
| trees:2 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic only, tree:0 filter' ' |
| test-tool path-walk --filter=tree:0 -- topic >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| blobs:0 |
| commits:3 |
| tags:0 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'tree:1 filter is rejected' ' |
| test_must_fail test-tool path-walk --filter=tree:1 -- --all 2>err && |
| test_grep "tree:1 filter not supported by the path-walk API" err |
| ' |
| |
| test_expect_success 'all, object:type=commit filter' ' |
| test-tool path-walk --filter=object:type=commit -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| blobs:0 |
| commits:4 |
| tags:0 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, object:type=tag filter' ' |
| test-tool path-walk --filter=object:type=tag -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:tag:/tags:$(git rev-parse refs/tags/first) |
| 0:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 0:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 0:tag:/tags:$(git rev-parse refs/tags/third) |
| 0:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 0:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 0:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| blobs:0 |
| commits:0 |
| tags:7 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, object:type=tree filter' ' |
| test-tool path-walk --filter=object:type=tree -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:tree::$(git rev-parse topic^{tree}) |
| 0:tree::$(git rev-parse base^{tree}) |
| 0:tree::$(git rev-parse base~1^{tree}) |
| 0:tree::$(git rev-parse base~2^{tree}) |
| 1:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{}) |
| 1:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2^{}) |
| 2:tree:a/:$(git rev-parse base:a) |
| 3:tree:child/:$(git rev-parse refs/tags/tree-tag:child) |
| 4:tree:left/:$(git rev-parse base:left) |
| 4:tree:left/:$(git rev-parse base~2:left) |
| 5:tree:right/:$(git rev-parse topic:right) |
| 5:tree:right/:$(git rev-parse base~1:right) |
| 5:tree:right/:$(git rev-parse base~2:right) |
| blobs:0 |
| commits:0 |
| tags:0 |
| trees:13 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, object:type=blob filter' ' |
| test-tool path-walk --filter=object:type=blob -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 1:blob:a:$(git rev-parse base~2:a) |
| 2:blob:left/b:$(git rev-parse base:left/b) |
| 2:blob:left/b:$(git rev-parse base~2:left/b) |
| 3:blob:right/c:$(git rev-parse base~2:right/c) |
| 3:blob:right/c:$(git rev-parse topic:right/c) |
| 4:blob:right/d:$(git rev-parse base~1:right/d) |
| blobs:8 |
| commits:0 |
| tags:0 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, combine:blob:none+tree:0 filter' ' |
| test-tool path-walk \ |
| --filter=combine:blob:none+tree:0 -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tag:/tags:$(git rev-parse refs/tags/first) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 1:tag:/tags:$(git rev-parse refs/tags/third) |
| 1:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{tree}) |
| 3:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2) |
| blobs:2 |
| commits:4 |
| tags:7 |
| trees:2 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, combine:object:type=blob+blob:limit=3 filter' ' |
| test-tool path-walk \ |
| --filter=combine:object:type=blob+blob:limit=3 \ |
| -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 1:blob:a:$(git rev-parse base~2:a) |
| 2:blob:left/b:$(git rev-parse base~2:left/b) |
| 3:blob:right/c:$(git rev-parse base~2:right/c) |
| 4:blob:right/d:$(git rev-parse base~1:right/d) |
| blobs:6 |
| commits:0 |
| tags:0 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'all, combine of disjoint object:types is empty' ' |
| test-tool path-walk \ |
| --filter=combine:object:type=blob+object:type=tree \ |
| -- --all >out && |
| |
| cat >expect <<-EOF && |
| blobs:0 |
| commits:0 |
| tags:0 |
| trees:0 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'combine: rejects unsupported subfilters' ' |
| test_must_fail test-tool path-walk \ |
| --filter=combine:tree:1+blob:none -- --all 2>err && |
| test_grep "tree:1 filter not supported by the path-walk API" err |
| ' |
| |
| test_expect_success 'setup sparse filter blob' ' |
| # Cone-mode patterns: include root, exclude all dirs, include left/ |
| cat >patterns <<-\EOF && |
| /* |
| !/*/ |
| /left/ |
| EOF |
| sparse_oid=$(git hash-object -w -t blob patterns) |
| ' |
| |
| test_expect_success 'all, sparse:oid filter' ' |
| test-tool path-walk --filter=sparse:oid=$sparse_oid -- --all >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tag:/tags:$(git rev-parse refs/tags/first) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.1) |
| 1:tag:/tags:$(git rev-parse refs/tags/second.2) |
| 1:tag:/tags:$(git rev-parse refs/tags/third) |
| 1:tag:/tags:$(git rev-parse refs/tags/fourth) |
| 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) |
| 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) |
| 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) |
| 3:tree::$(git rev-parse topic^{tree}) |
| 3:tree::$(git rev-parse base^{tree}) |
| 3:tree::$(git rev-parse base~1^{tree}) |
| 3:tree::$(git rev-parse base~2^{tree}) |
| 4:blob:a:$(git rev-parse base~2:a) |
| 5:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{}) |
| 5:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2^{}) |
| 6:blob:file2:$(git rev-parse refs/tags/tree-tag2^{}:file2) |
| 7:tree:a/:$(git rev-parse base:a) |
| 8:tree:child/:$(git rev-parse refs/tags/tree-tag:child) |
| 9:tree:left/:$(git rev-parse base:left) |
| 9:tree:left/:$(git rev-parse base~2:left) |
| 10:blob:left/b:$(git rev-parse base~2:left/b) |
| 10:blob:left/b:$(git rev-parse base:left/b) |
| 11:tree:right/:$(git rev-parse topic:right) |
| 11:tree:right/:$(git rev-parse base~1:right) |
| 11:tree:right/:$(git rev-parse base~2:right) |
| blobs:6 |
| commits:4 |
| tags:7 |
| trees:13 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_expect_success 'topic only, sparse:oid filter' ' |
| test-tool path-walk --filter=sparse:oid=$sparse_oid -- topic >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse topic) |
| 0:commit::$(git rev-parse base~1) |
| 0:commit::$(git rev-parse base~2) |
| 1:tree::$(git rev-parse topic^{tree}) |
| 1:tree::$(git rev-parse base~1^{tree}) |
| 1:tree::$(git rev-parse base~2^{tree}) |
| 2:blob:a:$(git rev-parse base~2:a) |
| 3:tree:left/:$(git rev-parse base~2:left) |
| 4:blob:left/b:$(git rev-parse base~2:left/b) |
| 5:tree:right/:$(git rev-parse topic:right) |
| 5:tree:right/:$(git rev-parse base~1:right) |
| 5:tree:right/:$(git rev-parse base~2:right) |
| blobs:2 |
| commits:3 |
| tags:0 |
| trees:7 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| # Demonstrate the SEEN flag ordering issue: when the same tree/blob OID |
| # appears at two sibling paths where one is in-cone and the other is |
| # out-of-cone, the path-walk must still discover blobs at the in-cone |
| # path even when the shared tree OID was first encountered out-of-cone. |
| # Since sparse:oid includes all trees, the out-of-cone tree (aaa/) is |
| # walked first, and its blob is skipped. The path-walk then re-walks |
| # the same tree OID at the in-cone path (zzz/) to find the blob there. |
| |
| test_expect_success 'setup shared tree OID across cone boundary' ' |
| git checkout --orphan shared-tree && |
| git rm -rf . && |
| mkdir aaa zzz && |
| echo "shared content" >aaa/file && |
| echo "shared content" >zzz/file && |
| echo "root file" >rootfile && |
| git add aaa zzz rootfile && |
| git commit -m "aaa and zzz have same tree OID" && |
| |
| # Verify they really share a tree OID |
| aaa_tree=$(git rev-parse HEAD:aaa) && |
| zzz_tree=$(git rev-parse HEAD:zzz) && |
| test "$aaa_tree" = "$zzz_tree" && |
| |
| # Cone pattern: include root + zzz/ (not aaa/) |
| cat >shared-patterns <<-\EOF && |
| /* |
| !/*/ |
| /zzz/ |
| EOF |
| shared_sparse_oid=$(git hash-object -w -t blob shared-patterns) |
| ' |
| |
| test_expect_success 'sparse:oid with shared tree OID across cone boundary' ' |
| test-tool path-walk \ |
| --filter=sparse:oid=$shared_sparse_oid \ |
| -- shared-tree >out && |
| |
| cat >expect <<-EOF && |
| 0:commit::$(git rev-parse shared-tree) |
| 1:tree::$(git rev-parse shared-tree^{tree}) |
| 2:blob:rootfile:$(git rev-parse shared-tree:rootfile) |
| 3:tree:aaa/:$(git rev-parse shared-tree:aaa) |
| 4:tree:zzz/:$(git rev-parse shared-tree:zzz) |
| 5:blob:zzz/file:$(git rev-parse shared-tree:zzz/file) |
| blobs:2 |
| commits:1 |
| tags:0 |
| trees:3 |
| EOF |
| |
| test_cmp_sorted expect out |
| ' |
| |
| test_done |