Skip to main content

Module pack_walk

Module pack_walk 

Source
Expand description

One pass over a pushed packfile’s entries — the split the closure check falls out of. Ours, gated against gix’s grammar entry for entry. The split: one pass over a pushed packfile’s entries, and nothing else.

This is what crate::store’s put_pack walks before it stores a byte, and it is the reason the closure check costs nothing extra (§13.7): the walk has to visit every entry anyway to find where the next one starts, so the set of entry boundaries and the set of delta bases fall out of it for free. No index is consulted to answer is this pack self-contained.

§What it does NOT do

It does not compute oids. An entry’s oid is sha1("<type> <size>\0" ‖ inflated content), and for a delta that content only exists after the chain is resolved — that is git index-pack’s job, it is the indexer’s work by §13.9 (“the index is built after the ack, over a channel”), and it is deliberately not on the ack path. So a [PackEntry] carries the five facts the pack itself states — extent, type, declared size and delta base — and no more.

§Why the bytes are inflated but the output is thrown away

A pack entry has no length field. The only way to find entry n+1 is to run the zlib stream of entry n to its end and ask the decompressor how many input bytes it consumed. So the walk pays one inflate over the pack — but it never materialises an object: the output goes into one reusable [SCRATCH]-sized buffer and is discarded, so peak memory is the scratch buffer and not the repository. total_out is still checked against the declared size, because a stream that inflates to a different length than its header claims is a corrupt pack and the honest answer is an error.

§Whose grammar is this

Ours, and §18 is the reason it is allowed to be: the plan records the choice between keeping gix as a grammar library and writing the two parsers ourselves as open, and it prescribes exactly how to settle it — “write the two parsers, and gate them behind a test that runs both ours and gix’s over a real corpus and requires byte-identical output on every entry”. That gate is [tests::ours_and_gix_agree_on_every_entry_of_every_pack], which drives gix_pack::data::input::BytesToEntriesIter (a dev-dependency, so no gix crate enters a shipped archiver) over the same bytes and requires the five facts to match entry for entry. Writing the parser is therefore executing the plan’s decision procedure, not pre-empting its decision: if the gate ever fails, gix is the arbiter and this module is wrong.

The one dependency it adds is flate2 on its pure-Rust zlib-rs backend — the same crate and the same backend ldeflate already pulls in non-optionally through znippy-common, so the build graph is unchanged: no C, no cmake, no build-script network, and --no-default-features still builds in seconds.

Structs§

Closure
What the closure check found. Derived from the walk alone — no index, no disk, no oid resolution.
EmitEntry
One object to emit: where its stored entry is, and what it deltas against.
EmitReport
What emitting produced, in facts a caller can assert on.
PackEntry
One entry, as the pack itself states it.
PackWalk
What one pass over a pack found.

Enums§

DeltaBase
Where a delta entry’s base is.
EntryBytes
Where an entry’s bytes are — an address into the archive, or bytes that exist nowhere else.

Functions§

emit_pack
Assemble ordered entries into a packfile.
encode_ofs_distance
Encode an OFS_DELTA backwards distance — the inverse of [ofs_distance].
encode_type_and_size
Encode the type/size header — the inverse of [type_and_size].
header_len
How many bytes of a stored entry are header — everything before the compressed payload.
ofs_distance_of
An OFS_DELTA’s backwards distance to its base, and how many bytes it occupied. b starts immediately after the type/size varint.
resolve_against
One entry’s bytes, resolved against a buffer that spans the archive’s coordinate space — the in-memory resolver, and the one emit_pack’s callers use when the archive is a &[u8] rather than a mapping.
topological_order
Order entries so that every delta follows the base it names.
type_and_size_of
The type/size varint, for a caller outside this module that needs to find where an entry’s header ends — reading the grammar rather than assuming a width.
walk
Walk a pushed pack’s entries.