1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//! Location-independent model resolution. An installed `steeldb` binary must find its bundled models
//! whatever the working directory is — so we search, in priority order: an explicit env override, the
//! per-user cache (`~/.steeldb/models`, `%LOCALAPPDATA%\steeldb\models`), next-to-the-executable
//! (`<exe>/models`, and `<exe>/../../models` for the dev `target/<profile>/` layout), then `./models`.
use std::path::PathBuf;
/// Candidate `models/` roots, most-preferred first.
pub fn model_roots() -> Vec<PathBuf> {
let mut roots = Vec::new();
if let Ok(r) = std::env::var("STEELDB_MODELS") {
roots.push(PathBuf::from(r));
}
if let Ok(home) = std::env::var("HOME") {
roots.push(PathBuf::from(home).join(".steeldb/models"));
}
if let Ok(la) = std::env::var("LOCALAPPDATA") {
roots.push(PathBuf::from(la).join("steeldb").join("models"));
}
if let Ok(exe) = std::env::current_exe() {
if let Some(dir) = exe.parent() {
roots.push(dir.join("models")); // installed: models next to the binary
roots.push(dir.join("..").join("..").join("models")); // dev: target/<profile>/ → repo/models
}
}
roots.push(PathBuf::from("models")); // CWD fallback (running from repo root)
roots
}
/// Resolve a model sub-directory. An explicit `env_var` wins (if it points at a dir containing
/// `marker`); otherwise the first `<root>/<name>` that contains `marker`. `marker` is a file that must
/// exist so we don't return an empty/partial dir.
pub fn model_dir(name: &str, env_var: &str, marker: &str) -> Option<PathBuf> {
if let Ok(p) = std::env::var(env_var) {
let p = PathBuf::from(p);
if p.join(marker).exists() {
return Some(p);
}
}
model_roots().into_iter().map(|r| r.join(name)).find(|d| d.join(marker).exists())
}