pack
zpack pack <input-dir> <output.zpak>Walks input-dir recursively and writes every regular file into a new archive
at output.zpak.
$ zpack pack assets/ game.zpakPacked 56 files (77.2 MiB -> 71.7 MiB, 7.1% smaller)When compression saved nothing, the summary drops the comparison:
$ zpack pack photos/ photos.zpakPacked 212 files (1.4 GiB)What gets packed
Section titled “What gets packed”Only regular files. Directories are implied by entry paths, so an empty one is not preserved. Symlinks, devices, and sockets are skipped.
Paths are stored relative to input-dir and normalized to / on every
platform, so an archive packed on Windows extracts identically on Linux.
Four things are left out:
- Anything matching a pattern in
input-dir/.zpackignore- see .zpackignore - The
.zpackignorefile itself; it describes how to build the archive, not what it holds - A file whose relative path equals
output.zpak, sozpack pack . out.zpakis repeatable - The temporary file
packbuilds into, which is created after the scan and so cannot appear in its own archive
Compression
Section titled “Compression”Each file is compressed with raw deflate at level 6. If the compressed form is
not smaller than the original, pack rewinds and writes the file verbatim,
recording it as store. Already-compressed assets therefore never grow.
There is no compression level flag. The rewind costs a second read of the source file, which is the price of never producing a larger archive than the input.
Atomicity
Section titled “Atomicity”The archive is built in a temporary file beside the destination and moved into
place only once it is complete. A run that fails partway - a disk filling up, a
source file vanishing - leaves any existing archive at output.zpak
untouched, rather than replacing it with a truncated one.
Reproducibility
Section titled “Reproducibility”Entries are sorted by path before the index is written, so directory walk order does not leak into the output:
$ zpack pack assets/ a.zpak$ zpack pack assets/ b.zpak$ cmp a.zpak b.zpak # identicalFailures
Section titled “Failures”| Message | Cause |
|---|---|
cannot open directory '<dir>': FileNotFound |
input-dir does not exist |
cannot pack '<dir>': AssetIdCollision |
Two paths hash to the same asset id. A build error by design, not a warning - see asset handles |
cannot pack '<dir>': InvalidPath |
A filename that cannot round-trip: non-UTF-8, or containing \, :, or NUL |
cannot pack '<dir>': PathTooLong |
A path over 65535 bytes |
cannot pack '<dir>': TooManyFiles |
More than 4294967295 files |
cannot pack '<dir>': TooManyRules |
More than 1024 rules in .zpackignore |
cannot pack '<dir>': SourceChanged |
A file changed size between being compressed and being re-read for the store fallback |
Memory
Section titled “Memory”Directory metadata is held in an arena and discarded when the command returns. File contents stream through reused 64 KiB buffers and are never held whole. One deflate compressor - around 230 KB - is allocated once and reused for every file.
Packing a 40 GB tree uses the same working set as packing a 40 MB one.