@@ -1,0 +1,177 @@
defmodule ExGitObjectstore.WalkTest do
use ExUnit.Case, async: true
alias ExGitObjectstore.Object
alias ExGitObjectstore.Object.{Blob, Commit, Tree}
alias ExGitObjectstore.Test.RepoHelper
setup do
repo = RepoHelper.memory_repo()
ExGitObjectstore.init(repo)
# Build a chain of 5 commits
blob = Blob.from_content("content\n")
{:ok, blob_sha} = Object.write(repo, blob)
tree = Tree.new([%{mode: "100644", name: "file.txt", sha: blob_sha}])
{:ok, tree_sha} = Object.write(repo, tree)
# Commit 1 (oldest)
c1 = %Commit{
tree: tree_sha,
parents: [],
author: "A <a@a.com> 1000000000 +0000",
committer: "A <a@a.com> 1000000000 +0000",
message: "first\n"
}
{:ok, c1_sha} = Object.write(repo, c1)
# Commit 2
c2 = %Commit{
tree: tree_sha,
parents: [c1_sha],
author: "A <a@a.com> 1000000001 +0000",
committer: "A <a@a.com> 1000000001 +0000",
message: "second\n"
}
{:ok, c2_sha} = Object.write(repo, c2)
# Commit 3
c3 = %Commit{
tree: tree_sha,
parents: [c2_sha],
author: "A <a@a.com> 1000000002 +0000",
committer: "A <a@a.com> 1000000002 +0000",
message: "third\n"
}
{:ok, c3_sha} = Object.write(repo, c3)
# Commit 4
c4 = %Commit{
tree: tree_sha,
parents: [c3_sha],
author: "A <a@a.com> 1000000003 +0000",
committer: "A <a@a.com> 1000000003 +0000",
message: "fourth\n"
}
{:ok, c4_sha} = Object.write(repo, c4)
# Commit 5 (newest)
c5 = %Commit{
tree: tree_sha,
parents: [c4_sha],
author: "A <a@a.com> 1000000004 +0000",
committer: "A <a@a.com> 1000000004 +0000",
message: "fifth\n"
}
{:ok, c5_sha} = Object.write(repo, c5)
ExGitObjectstore.create_branch(repo, "main", c5_sha)
%{
repo: repo,
shas: [c1_sha, c2_sha, c3_sha, c4_sha, c5_sha],
tree_sha: tree_sha
}
end
describe "log" do
test "returns all commits in reverse chronological order", %{repo: repo, shas: shas} do
{:ok, log} = ExGitObjectstore.log(repo, "main")
log_shas = Enum.map(log, &elem(&1, 0))
assert length(log) == 5
# Newest first
assert List.first(log_shas) == List.last(shas)
assert List.last(log_shas) == List.first(shas)
end
test "max_count limits results", %{repo: repo} do
{:ok, log} = ExGitObjectstore.log(repo, "main", max_count: 3)
assert length(log) == 3
end
test "skip skips commits", %{repo: repo} do
{:ok, all} = ExGitObjectstore.log(repo, "main")
{:ok, skipped} = ExGitObjectstore.log(repo, "main", skip: 2)
assert length(skipped) == 3
assert Enum.map(skipped, &elem(&1, 0)) == Enum.map(all, &elem(&1, 0)) |> Enum.drop(2)
end
test "max_count and skip together", %{repo: repo} do
{:ok, log} = ExGitObjectstore.log(repo, "main", max_count: 2, skip: 1)
assert length(log) == 2
end
end
describe "commit" do
test "get commit by ref", %{repo: repo, shas: shas} do
{:ok, {sha, commit}} = ExGitObjectstore.commit(repo, "main")
assert sha == List.last(shas)
assert %Commit{message: "fifth\n"} = commit
end
test "get commit by SHA", %{repo: repo, shas: [first_sha | _]} do
{:ok, {sha, commit}} = ExGitObjectstore.commit(repo, first_sha)
assert sha == first_sha
assert commit.message == "first\n"
end
end
describe "tree" do
test "get root tree for commit", %{repo: repo} do
{:ok, tree} = ExGitObjectstore.tree(repo, "main")
assert %Tree{entries: [entry]} = tree
assert entry.name == "file.txt"
end
test "tree path traversal" do
repo = RepoHelper.memory_repo()
ExGitObjectstore.init(repo)
# Create nested structure: src/main.ex
inner_blob = Blob.from_content("code\n")
{:ok, inner_sha} = Object.write(repo, inner_blob)
inner_tree = Tree.new([%{mode: "100644", name: "main.ex", sha: inner_sha}])
{:ok, inner_tree_sha} = Object.write(repo, inner_tree)
root_tree = Tree.new([%{mode: "40000", name: "src", sha: inner_tree_sha}])
{:ok, root_tree_sha} = Object.write(repo, root_tree)
commit = %Commit{
tree: root_tree_sha,
parents: [],
author: "A <a@a.com> 1000000000 +0000",
committer: "A <a@a.com> 1000000000 +0000",
message: "init\n"
}
{:ok, commit_sha} = Object.write(repo, commit)
ExGitObjectstore.create_branch(repo, "main", commit_sha)
# Get src/ subtree
{:ok, src_tree} = ExGitObjectstore.tree(repo, "main", "src")
assert %Tree{entries: [entry]} = src_tree
assert entry.name == "main.ex"
end
end
describe "blob" do
test "get blob content by SHA", %{repo: repo} do
blob = Blob.from_content("test content")
{:ok, sha} = Object.write(repo, blob)
assert {:ok, "test content"} = ExGitObjectstore.blob(repo, sha)
end
test "blob_size returns byte count", %{repo: repo} do
blob = Blob.from_content("12345")
{:ok, sha} = Object.write(repo, blob)
assert {:ok, 5} = ExGitObjectstore.blob_size(repo, sha)
end
end
end