Expand description
The client half: pkt-line framing over a blocking stream, and the
send_pack driver that runs one whole push.
§The conversation, exactly
S→C <old-oid> <refname>\0<capabilities>\n ref advertisement, protocol v0
S→C <old-oid> <refname>\n …one line per ref
S→C 0000
C→S <old> <new> <refname>\0<capabilities>\n the command list
C→S <old> <new> <refname>\n …one line per ref being moved
C→S 0000
C→S <push-option>\n … 0000 only if `push-options` was negotiated
C→S PACK… raw, NOT pkt-line framed
S→C unpack ok\n report-status
S→C ok refs/heads/main\n | ng refs/heads/x <why>\n
S→C 0000Three details are where implementations go wrong, and each has a test:
- The packfile is not framed. It follows the flush-pkt as raw bytes. Framing it is a corrupt push with a checksum error and no clue pointing at the framing layer.
- An all-deletes push sends no pack at all. Sending an empty pack is also legal, but sending one for a push that introduces no objects is a lie about what the client did.
- With
side-band-64k, the report is muxed inside band 1, pkt-lines nested inside pkt-lines, and the remote’s hook output arrives on band 2. Reading the report without demuxing yields a leading\x01on every line and a parse that fails in a way that looks like a protocol error.
Functions§
- encode_
command_ list - The command list, framed and flush-terminated.
- encode_
push_ options - The push-options section, framed and flush-terminated.
- frame_
section - Frame
linesas text pkt-lines and terminate with a flush-pkt. - read_
advertisement - Read
git-receive-pack’s ref advertisement fromreader. - read_
report - Read the report from
reader, demultiplexing sidebands when negotiated. - send_
pack - Run one complete send-pack over
transport, given an advertisement already read from it.