From 334faeb000a72b96081dc2d61a51f367abcef586 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 24 Jun 2026 11:54:14 +0300 Subject: [PATCH] =?UTF-8?q?feat(common):=20Layout=20=E2=80=94=20=D0=BA?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=BD=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=83=D1=82=D0=B8=20/data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- crates/shturman-common/src/paths.rs | 64 ++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/crates/shturman-common/src/paths.rs b/crates/shturman-common/src/paths.rs index 33bed61..9a45872 100644 --- a/crates/shturman-common/src/paths.rs +++ b/crates/shturman-common/src/paths.rs @@ -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) -> 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")); + } +}