ref:4dd9e11aa8545cb03121025053d1a2a06e8ba62c

test: add protocol interop tests with real git CLI packs (closes #8)

16 integration tests that exercise ReceivePack and UploadPack with real git-generated pack data (delta compression, thin packs, binary files, merge commits, force push, multi-branch, annotated tags, round-trip verification, adversarial packs). Also fix credo issues in diff module. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SHA: 4dd9e11aa8545cb03121025053d1a2a06e8ba62c
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-03-14 02:52
Parents: b18689e
3 files changed +871 -42
Type
lib/ex_git_objectstore/diff.ex +23 −21
@@ -94,24 +94,24 @@
with {:ok, old_commit} <- ObjectResolver.read(repo, old_commit_sha),
{:ok, new_commit} <- ObjectResolver.read(repo, new_commit_sha),
{:ok, changes} <- diff_trees(repo, old_commit.tree, new_commit.tree) do
file_diffs =
Enum.map(changes, fn change ->
case diff_blobs(repo, change.old_sha, change.new_sha, opts) do
{:ok, :binary, sizes} ->
%{
path: change.path,
status: change.status,
hunks: [],
binary: true,
old_size: sizes.old_size,
new_size: sizes.new_size
}
file_diffs = Enum.map(changes, &build_file_diff(repo, &1, opts))
{:ok, file_diffs}
end
end
defp build_file_diff(repo, change, opts) do
{:ok, hunks} ->
%{path: change.path, status: change.status, hunks: hunks}
end
end)
case diff_blobs(repo, change.old_sha, change.new_sha, opts) do
{:ok, :binary, sizes} ->
%{
path: change.path,
status: change.status,
hunks: [],
binary: true,
old_size: sizes.old_size,
new_size: sizes.new_size
}
{:ok, file_diffs}
{:ok, hunks} ->
%{path: change.path, status: change.status, hunks: hunks}
end
end
@@ -321,11 +321,13 @@
|> merge_ranges()
# Build a hunk from each merged range
Enum.map(ranges, fn {start_idx, end_idx} ->
lines = for i <- start_idx..end_idx, do: :array.get(i, indexed_vec)
build_hunk(lines)
end)
Enum.map(ranges, &range_to_hunk(&1, indexed_vec))
end
end
defp range_to_hunk({start_idx, end_idx}, indexed_vec) do
lines = for i <- start_idx..end_idx, do: :array.get(i, indexed_vec)
build_hunk(lines)
end
defp merge_ranges([]), do: []