Skip to content
This repository has been archived by the owner on Oct 8, 2020. It is now read-only.

Commit

Permalink
Fix bugs in handling of basic pack decoding.
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten committed May 25, 2020
1 parent bdf2564 commit 24c30a8
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 8 deletions.
36 changes: 28 additions & 8 deletions lib/xgit/pack_reader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ defmodule Xgit.PackReader do
cover {:error, :invalid_object}
end

@read_chunk_size 64
@read_chunk_size 4096

defp unpack_object(_reader, pack_iodevice, object_id, type, size) do
Temp.track!()
Expand All @@ -448,7 +448,7 @@ defmodule Xgit.PackReader do
with :ok <- :zlib.inflateInit(z),
{:ok, path} <- Temp.path(),
{:ok, unpacked_iodevice} <- File.open(path, [:write, :binary]),
:ok <- inflate_object(z, pack_iodevice, unpacked_iodevice, {:continue, ""}),
:ok <- inflate_object(z, pack_iodevice, unpacked_iodevice, {:start, ""}, size),
:ok <- File.close(unpacked_iodevice) do
cover {:ok,
%Object{
Expand All @@ -462,17 +462,37 @@ defmodule Xgit.PackReader do
end
end

defp inflate_object(_z, _pack_iodevice, _unpacked_iodevice, {:finished, []}) do
cover :ok
defp inflate_object(z, _pack_iodevice, _unpacked_iodevice, {:finished, []}, remaining_size)
when remaining_size <= 0 do
:ok = :zlib.close(z)
end

defp inflate_object(z, pack_iodevice, unpacked_iodevice, {_verb, data}) do
defp inflate_object(z, pack_iodevice, unpacked_iodevice, {:continue, data}, remaining_size) do
with :ok <- IO.binwrite(unpacked_iodevice, data) do
inflate_object(
z,
pack_iodevice,
unpacked_iodevice,
:zlib.safeInflate(z, ""),
remaining_size - IO.iodata_length(data)
)
else
_ -> :error
end
end

defp inflate_object(z, pack_iodevice, unpacked_iodevice, {_verb, data}, remaining_size) do
with :ok <- IO.binwrite(unpacked_iodevice, data),
next_data when is_binary(next_data) <- IO.binread(pack_iodevice, @read_chunk_size) do
inflate_object(z, pack_iodevice, unpacked_iodevice, :zlib.safeInflate(z, next_data))
inflate_object(
z,
pack_iodevice,
unpacked_iodevice,
:zlib.safeInflate(z, next_data),
remaining_size - IO.iodata_length(data)
)
else
:eof -> cover :ok
_ -> cover :error
_ -> :error
end
end

Expand Down
21 changes: 21 additions & 0 deletions test/xgit/pack_reader_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -203,5 +203,26 @@ defmodule Xgit.PackReaderTest do
Deleted Linus' header.
'''
end

test "can read first blob in pack", %{reader: reader} do
assert {:ok,
%Object{
content: content,
size: 18787,
id: "6ff87c4664981e4397625791c8ea3bbb5f2279a3",
type: :blob
}} = PackReader.get_object(reader, "6ff87c4664981e4397625791c8ea3bbb5f2279a3")

rendered_content =
content
|> ContentSource.stream()
|> Enum.to_list()
|> IO.iodata_to_binary()

assert byte_size(rendered_content) == 18787

assert String.starts_with?(rendered_content, "\n Note that the only")
assert String.ends_with?(rendered_content, "nstead of this License.\n")
end
end
end

0 comments on commit 24c30a8

Please sign in to comment.