Files
dtourolleandClaude Opus 5 e26f71d15d Gather every model under one tree at the repository root
The weights were in two places: face detection and recognition in
`models/face/`, segmentation in `core/dr-segment/models/`. Nothing was
wrong with either path, but between them there was nowhere to look to
answer "how much model does this application carry", and that number is
about to start growing.

So the crate-local copy moves up beside the other. `models/` now holds
`face/` and `segment/`, and a `du -sh` of one directory is the whole
answer.

No content changes: the .onnx and its vocabulary are byte-identical, and
`LICENCE.md` moves up a level to cover the tree rather than one crate.
The LFS pattern in `.gitattributes` is `*.onnx` and already matched both
locations, so only its comment needed the new path.

`include_bytes!` is relative to the source file and `build.rs` runs with
the crate root as its working directory, which is why the two paths climb
a different number of levels.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 10:05:04 +02:00

59 lines
2.3 KiB
Rust

//! Check the model is a model and not an LFS pointer.
//!
//! `models/segment/*.onnx` is stored in Git LFS (see `.gitattributes`). A clone made
//! without git-lfs installed, or with `GIT_LFS_SKIP_SMUDGE` set, leaves a
//! ~130-byte text pointer at that path instead of the weights.
//!
//! Without this check `include_bytes!` would happily embed the pointer, the
//! crate would compile, and the failure would surface much later as an opaque
//! ONNX parse error from inside tract — at which point the connection back to
//! a missing `git lfs pull` is not one anybody would make quickly. Failing
//! here costs one file read and turns that into a sentence.
use std::path::Path;
const MODEL: &str = "../../models/segment/yolo26n-seg.onnx";
fn main() {
println!("cargo:rerun-if-changed={MODEL}");
println!("cargo:rerun-if-changed=build.rs");
// Only the embedded path needs the file present; a build without it is
// watershed-only by choice and should not be blocked on weights.
if std::env::var_os("CARGO_FEATURE_EMBEDDED_MODEL").is_none() {
return;
}
let path = Path::new(MODEL);
let Ok(bytes) = std::fs::read(path) else {
panic!(
"\n\n{MODEL} is missing.\n\
It ships in Git LFS. Run `git lfs install && git lfs pull`, or build \
with `--no-default-features` for a watershed-only build.\n"
);
};
// ONNX is protobuf, which has no magic number; an LFS pointer is short
// ASCII beginning with a version URL. Testing for the pointer is the
// reliable direction — it has a known shape, where "valid protobuf" does
// not, and this check only has to catch the one failure that actually
// happens in practice.
if bytes.starts_with(b"version https://git-lfs") {
panic!(
"\n\n{MODEL} is a Git LFS pointer, not the model ({} bytes).\n\
Run `git lfs install && git lfs pull` to fetch the real file.\n",
bytes.len()
);
}
// A model that parses as a pointer-sized file is not one either. The real
// export is ~11 MB; anything under a megabyte is a truncated checkout.
if bytes.len() < 1_000_000 {
panic!(
"\n\n{MODEL} is only {} bytes — expected ~11 MB.\n\
The checkout looks incomplete; try `git lfs pull`.\n",
bytes.len()
);
}
}