feat(common): Layout — канонические пути /data

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 11:54:14 +03:00
parent 4ee012127f
commit 334faeb000
+63 -1
View File
@@ -1 +1,63 @@
//! Канонические пути персистентного раздела `/data` (наполняется в Task 2).
//! Канонические пути персистентного раздела `/data` (a-base §3, §11).
//! Все писатели в `/data` берут пути отсюда — без хардкода. Корень настраивается
//! (тесты/dev) — по умолчанию `/data` или env `SHTURMAN_DATA_DIR`.
use std::path::{Path, PathBuf};
/// Раскладка `/data`.
#[derive(Debug, Clone)]
pub struct Layout {
root: PathBuf,
}
impl Layout {
/// Явный корень (тесты, known-mount).
pub fn new(root: impl Into<PathBuf>) -> Self {
Self { root: root.into() }
}
/// Корень из окружения (`SHTURMAN_DATA_DIR`) или дефолт `/data`.
pub fn from_env() -> Self {
let root = std::env::var_os("SHTURMAN_DATA_DIR")
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::from("/data"));
Self { root }
}
pub fn root(&self) -> &Path {
&self.root
}
pub fn apps(&self) -> PathBuf {
self.root.join("apps")
}
pub fn settings(&self) -> PathBuf {
self.root.join("settings")
}
pub fn state(&self) -> PathBuf {
self.root.join("state")
}
pub fn log(&self) -> PathBuf {
self.root.join("log")
}
/// Маркер завершённого first-boot (§7.2).
pub fn provisioned_marker(&self) -> PathBuf {
self.root.join(".shturman-provisioned")
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn subdirs_are_under_root() {
let l = Layout::new("/tmp/x");
assert_eq!(l.root(), Path::new("/tmp/x"));
assert_eq!(l.apps(), Path::new("/tmp/x/apps"));
assert_eq!(l.settings(), Path::new("/tmp/x/settings"));
assert_eq!(l.state(), Path::new("/tmp/x/state"));
assert_eq!(l.log(), Path::new("/tmp/x/log"));
assert_eq!(l.provisioned_marker(), Path::new("/tmp/x/.shturman-provisioned"));
}
}