#!/bin/sh TEST_PASSES_SANITIZE_LEAK=true test_description='direct path-walk API tests' . ./test-lib.sh test_expect_success 'setup test repository' ' git checkout -b base && # Make some objects that will only be reachable # via non-commit tags. mkdir child && echo file >child/file && git add child && git commit -m "will abandon" && git tag -a -m "tree" tree-tag HEAD^{tree} && echo file2 >file2 && git add file2 && git commit --amend -m "will abandon" && git tag tree-tag2 HEAD^{tree} && echo blob >file && blob_oid=$(git hash-object -t blob -w --stdin file2 && blob2_oid=$(git hash-object -t blob -w --stdin a && echo b >left/b && echo c >right/c && git add . && git commit --amend -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}) 3:tree::$(git rev-parse refs/tags/tree-tag^{}) 3:tree::$(git rev-parse refs/tags/tree-tag2^{}) 4:blob:a:$(git rev-parse base~2:a) 5:blob:file2:$(git rev-parse refs/tags/tree-tag2^{}:file2) 6:tree:a/:$(git rev-parse base:a) 7:tree:child/:$(git rev-parse refs/tags/tree-tag:child) 8:blob:child/file:$(git rev-parse refs/tags/tree-tag:child/file) 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) 12:blob:right/c:$(git rev-parse base~2:right/c) 12:blob:right/c:$(git rev-parse topic:right/c) 13: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 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 '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_done