ref:cfb369231afdd490eb7d857276d885afdf0cf130

fix: treat only flush (0000) as v2 command terminator, not delim (0001)

`has_complete_command?` was matching on both flush and delim packets. Delim is an intra-command section separator between `command=...` and the argument block, NOT a terminator. When the request arrived split across multiple TCP chunks and the first chunk ended at the delim, the state machine processed an incomplete fetch request and transitioned to :done, silently dropping the rest. The integration test test "fetch request response is invariant under TCP chunking" exercises this directly — feeds a known-good fetch request through the state machine sliced at 20 different random offsets and asserts the response matches the whole-blob baseline. Closes #29.
SHA: cfb369231afdd490eb7d857276d885afdf0cf130
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-04-19 00:18
Parents: df64bdb
1 files changed +7 -8
Type
lib/ex_git_objectstore/protocol/upload_pack_v2.ex +7 −8
@@ -82,14 +82,13 @@
end
defp has_complete_command?(data) do
# A complete v2 command is terminated by a flush (0000) or delim (0001) packet.
# Also treat data that fails pkt-line parsing as "complete" so we surface the error
# immediately rather than buffering forever.
# A complete v2 command is terminated by a flush (0000) packet. Delim
# (0001) is an intra-command section separator between the `command=`
# line and the argument block, so it's NOT a completion signal.
# Treat data that fails pkt-line parsing as "complete" so we surface
# the error immediately rather than buffering forever.
case PktLine.decode(data) do
{:ok, packets, _rest} ->
Enum.any?(packets, &(&1 in [:flush, :delim]))
{:error, _} ->
true
{:ok, packets, _rest} -> :flush in packets
{:error, _} -> true
end
end