Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

crates/gunnar-lfs/Cargo.toml

[package]
name = "gunnar-lfs"
description = "Git LFS over pure SSH: the git-lfs 3.0 `git-lfs-transfer` protocol, server side, streaming and without HTTP."
readme = "README.md"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
# On the `cargo install gunnar` chain (owner order 2026-10-22).
publish = true
authors.workspace = true
repository.workspace = true

# One `git-lfs-transfer` session on stdin/stdout. It is what a fake `ssh`
# wrapper execs so `tests/interop.rs` can drive the REAL git-lfs client at this
# protocol. The client only ever reaches a server by exec'ing a command over
# SSH, so a library test alone can never prove interop. Thin by construction:
# the same `open_or_init` + `Session::serve` pair `gunnar-cli`'s transport makes.
[[bin]]
name = "gunnar-lfs-serve"
path = "src/bin/serve.rs"
required-features = ["fs"]

[features]
default = []
# The on-disk object store. Off by default for the same reason
# `gunnar-store/fs` is: an appliance that has no filesystem must not link one.
# It costs NO new dependency: `std::fs` and nothing else.
fs = []

[dependencies]
# The framing, and the only place a pkt-line is parsed in gunnar (one
# implementation). Zero dependencies of its own.
gunnar-pktline = { workspace = true }

# SHA-256, streaming. An LFS oid is the SHA-256 of the object's RAW bytes, with no
# `<kind> <len>\0` header, so it is NOT a git object id and `gix_object::compute_hash`
# is the wrong function. `gix_hash::hasher(Kind::Sha256)` is the same `sha2`
# implementation gunnar already links for sha256 repositories, reached through the
# crate that already owns "which hash, and how" (see `gunnar-pack/src/checksum.rs`
# for the same argument in the other direction). No new dependency.
gix-hash = { workspace = true }

thiserror = { workspace = true }
tracing = { workspace = true }

# `tests/interop.rs` drives the REAL git-lfs binary against `gunnar-lfs-serve`,
# so it needs the `fs` backend that binary is built on. `required-features`
# rather than a `#[cfg]` inside the file: a cfg'd-out test compiles to nothing
# and reports nothing, which is indistinguishable from a test that ran. With
# this, a feature set that cannot run it does not list it either.
#
# `xtask ci` passes `--features gunnar-lfs/fs` precisely so the repository's
# own runner does run it.
[[test]]
name = "interop"
required-features = ["fs"]

# The TOCTOU proof needs bytes on a real disk: the whole point is that one
# client's upload has to become visible to another client's MEASUREMENT, and a
# `MemLfsStore` has no directory to walk. Same `required-features` argument as
# `interop` above — a cfg'd-out test reports nothing, which is
# indistinguishable from a test that ran.
[[test]]
name = "concurrent_allowance"
required-features = ["fs"]

[dev-dependencies]
tempfile = { workspace = true }
# `tests/swallowed_errors.rs` asserts that an abandoned upload which cannot be
# unlinked produces a LINE, not silence. A **dev**-dependency, so it is
# invisible to `cargo tree -e normal` and cannot reach the appliance graph
# the dependency budget guards.
tracing-subscriber = { workspace = true }
# `tests/authorisation.rs` frames the conversations a well-behaved client would
# never send, through the same encoder the server decodes with (one implementation).
gunnar-pktline = { workspace = true }
# `tests/interop.rs` computes what an oid *should* be, through the same crate
# that already owns "which sha256" for the server side (one implementation). Already a
# dependency above, so this costs nothing.
gix-hash = { workspace = true }

[lints.rust]
unsafe_code = "forbid"

# NO rayon — the multicore rule is gatling, never rayon. No subprocess, no
# HTTP, no new transport — LFS rides the SSH session. A single object's SHA-256 is serial by
# construction and cannot be parallelised, and the win for large objects is
# I/O, not CPU. See `src/lib.rs`.