Introduce src/server/ as a streaming-first git/lfs server surface. All
request and response bodies cross the API as
Box<dyn AsyncRead + Unpin + Send + Sync> (alias BoxedAsyncRead) — no
Vec<u8> bodies, no read_to_end convenience, no http crate.
What's in the box:
- src/server/mod.rs: re-exports + pipe re-export of
command::cmd::DEFAULT_OUTPUT_CAP_BYTES as server::DEFAULT_OUTPUT_CAP_BYTES
- src/server/backend.rs: ServerBackend async-trait (authorize,
list_refs_stream, produce_pack_stream, ingest_pack_stream,
lfs_get_stream, lfs_put_stream). Every method currently returns
ServerError::Unimplemented("...") placeholders — the wiring is
real, the bodies are intentionally empty.
- src/server/request.rs: ServerRequest (not Clone, body is a boxed
reader), HeaderMap = HashMap<String, String>, RefUpdateBatch
(oid strings, no gix::ObjectId), BoxedAsyncRead alias
- src/server/stream.rs: StreamGuard (Clone + Send + Sync) carrying
cancel() / handle() so spawned workers can race the request
- src/server/endpoint.rs, error.rs, limits.rs: EndpointKind enum,
ServerError, DEFAULT_LFS_OBJECT_CAP_BYTES (5 GiB cap, separate from
the 64 MiB output cap)
- tests/server.rs: PlaceholderBackend skeleton + ENV_LOCK +
200 ms cancel convention reused from tests/env.rs and tests/pipe.rs
Public API impact on GitBaby:
- Drop pipe from GitBaby::new — the server owns its own stream
lifecycle, so the Pipe parameter is no longer required at
construction time. Existing callers must be updated:
- before: GitBaby::new(facade, pipe)
- after: GitBaby::new(facade)
Documentation:
- AGENTS.md gains a "Planned but unimplemented (streaming-first
server)" section documenting the deliberately-empty contracts so
future contributors don't "fill them in" without a concrete
git/lfs protocol task.
CI: cargo build + cargo test (61 total, 23 new from server suite)
green.
Introduce a two-tier cache for blob payloads backed by the foyer crate
(memory + disk). The cache is configured via CacheConfig and exposed
through src/cache/{mod,global}.rs.
Why foyer:
- HybridCache gives us bounded RAM plus disk overflow without bringing
in our own eviction / spill logic.
- The runtime-tokio feature plays cleanly with the existing tokio stack.
Touches:
- src/cache/mod.rs: CacheConfig, CacheStore, CacheKey/Value aliases,
default-into-disk fallback (CacheConfig::default)
- src/cache/global.rs: process-wide singleton accessor for the default
cache
- src/error.rs: new BabyError::Cache { op, source } variant wrapping
foyer::Error so cache failures share the existing error pipeline
- Cargo.toml: add foyer = "0.22.3" with runtime-tokio feature
- src/lib.rs: pub mod cache; (wiring only — no public API on GitBaby
changes yet)
- src/tree/types.rs: drive-by import reorder (serde before std::path)
to match rustfmt
CI: cargo build + cargo test (38 passed) green.
Skipped intentionally: no git/lfs protocol logic is added here; this
commit is purely the storage substrate.
Add the serde 'twins' (Serialize + Deserialize) to every public struct
and enum in src/*/types.rs so data types can be serialized via JSON,
bincode, postcard, etc.
Dependency changes:
- enable 'serde' feature on gix (for gix::ObjectId)
- enable 'serde' feature on time (for time::OffsetDateTime)
Skipped:
- src/archive/types.rs::ChildArchiveReader<R> — contains a
tokio::process::Child field, semantically not serializable
Coverage (18 modules):
archive, blame, blob, branch, cleanup, commit, compare, config,
conflict, diff, merge, refs, remote, setup, submodule, tags, tree
Notes:
- field names kept snake_case (no rename_all remap)
- existing PartialEq / Eq / Default / Copy derives preserved
- cargo build + cargo test (38 passed) green