Lake is a Go library that provides a unified interface for reading and writing collections of files across different storage backends: filesystem directories, ZIP archives, and single files. It is part of the itch.io ecosystem and primarily used by wharf.
A Pool gives indexed read/seek access to an ordered list of files. Pools are backed by different storage types but expose the same interface:
type Pool interface {
GetSize(fileIndex int64) int64
GetReader(fileIndex int64) (io.Reader, error)
GetReadSeeker(fileIndex int64) (io.ReadSeeker, error)
Close() error
}WritablePool extends Pool with write access, and CaseFixerPool handles renaming on-disk files to match a container's expected casing (useful for case-insensitive filesystems).
The tlc.Container is a protobuf-based metadata format that captures a
complete directory structure: files, directories, and symlinks with their
sizes, permissions, and paths. Containers are produced by walking a directory or
ZIP archive, and can be used to recreate that structure on disk.
wharf embeds Container structs serialized
via protobuf in patch files (.pwr) and signature files to describe both the "old" and
"new" versions of a build, paired with binary diffs of the actual file
contents. butler is the CLI that drives
wharf to produce and apply these patches for itch.io uploads.
Lake does not define the patch format itself, it provides the filesystem abstraction layer and directory manifest that wharf builds on top of.
Core interfaces: Pool, WritablePool, CaseFixerPool, and case-fix
helpers.
Container type and filesystem operations:
- Walking:
WalkDir,WalkZip,WalkAny(auto-detects),WalkSingle - Preparing:
Container.Preparecreates all directories, files, and symlinks from a container spec - Validation: Container integrity checks
- Comparison: Diff containers to detect changes
- Permissions: Executable detection (ELF, Mach-O, shell scripts)
- Case handling: Cross-platform case-insensitive filesystem support
- Filtering:
FilterFuncand built-inPresetFilterto ignore VCS metadata, OS junk files, etc.
Pool implementations for different backends:
| Package | Description |
|---|---|
fspool |
Filesystem-backed pool (reads/writes files in a directory) |
zippool |
Read-only pool backed by a ZIP archive |
zipwriterpool |
Write-only pool that produces a ZIP archive |
cachepool |
Caching wrapper around another pool |
nullpool |
Discards all data (useful for testing and benchmarking) |
singlefilepool |
Writes a single file |
import (
"github.com/itchio/lake/tlc"
"github.com/itchio/lake/pools/fspool"
)
// Walk a directory to get its container (file listing)
container, err := tlc.WalkDir("/path/to/dir", tlc.WalkOpts{
Filter: tlc.PresetFilter,
})
// Open a filesystem pool for reading
pool := fspool.New(container, "/path/to/dir")
defer pool.Close()
reader, err := pool.GetReader(0) // read first fileMIT