Skip to content

Commit

Permalink
Apply deltas in GitRekt.WireProtocol.receive_pack
Browse files Browse the repository at this point in the history
See issue #1 for more details.
  • Loading branch information
redrabbit committed Dec 8, 2017
1 parent 0e7664b commit dd53dd5
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
1 change: 0 additions & 1 deletion apps/gitrekt/lib/gitrekt/packfile.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ defmodule GitRekt.Packfile do
cond do
obj_type == :delta_reference ->
<<base_oid::binary-20, rest::binary>> = rest
IO.puts "base oid: #{Git.oid_fmt(base_oid)}"
{delta, rest} = unpack_obj_data(rest)
{obj_type, unpack_obj_delta(base_oid, delta), rest}
true ->
Expand Down
32 changes: 25 additions & 7 deletions apps/gitrekt/lib/gitrekt/wire_protocol.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,8 @@ defmodule GitRekt.WireProtocol do
def receive_pack(repo, pkt) do
{refs, pack, caps} = parse_receive_pkt(pkt)
{:ok, odb} = Git.repository_get_odb(repo)
Enum.each(pack, fn
{:delta_reference, delta} ->
IO.inspect delta
{obj_type, obj_data} ->
{:ok, _} = Git.odb_write(odb, obj_data, obj_type)
end)
Enum.each(refs, fn {_old_oid, new_oid, refname} -> :ok = Git.reference_create(repo, refname, :oid, new_oid, true) end)
Enum.each(pack, &apply_pack_obj(odb, &1))
Enum.each(refs, &rename_ref(repo, &1))
if "report-status" in caps,
do: encode(["unpack ok", Enum.into(refs, "", &"ok #{elem(&1, 2)}"), :flush]),
else: []
Expand Down Expand Up @@ -122,6 +117,29 @@ defmodule GitRekt.WireProtocol do
end
end

defp rename_ref(repo, {_old_oid, new_oid, refname}) do
Git.reference_create(repo, refname, :oid, new_oid, true)
end

defp apply_pack_obj(odb, {:delta_reference, {base_oid, _base_obj_size, _result_obj_size, cmds}}) do
{:ok, obj_type, obj_data} = Git.odb_read(odb, base_oid)
new_data = apply_delta_chain(obj_data, "", cmds)
{:ok, _oid} = apply_pack_obj(odb, {obj_type, new_data})
end

defp apply_pack_obj(odb, {obj_type, obj_data}) do
{:ok, _oid} = Git.odb_write(odb, obj_data, obj_type)
end

defp apply_delta_chain(_source, target, []), do: target
defp apply_delta_chain(source, target, [{:insert, chunk}|cmds]) do
apply_delta_chain(source, target <> chunk, cmds)
end

defp apply_delta_chain(source, target, [{:copy, {offset, size}}|cmds]) do
apply_delta_chain(source, target <> binary_part(source, offset, size), cmds)
end

defp pkt_stream(data) do
Stream.resource(fn -> data end, &pkt_next/1, fn _ -> :ok end)
end
Expand Down

0 comments on commit dd53dd5

Please sign in to comment.