Skip to main content

unifier/
home.rs

1//! Resolve the unifier state root (`~/.local/unifier` by default) and optional chroots.
2
3use std::path::{Path, PathBuf};
4
5use crate::constants::CHROOTS;
6use crate::error::Result;
7use crate::scope::validate_chroot_name;
8
9const APP: &str = "unifier";
10
11/// Effective store root for the current invocation (global root or a chroot subtree).
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct UnifierHome {
14    global: PathBuf,
15    effective: PathBuf,
16    chroot: Option<String>,
17}
18
19impl UnifierHome {
20    /// Uses `$UNIFIER_HOME`, else `~/.local/unifier`. With `chroot`, scopes to `chroots/<name>/`.
21    pub fn resolve(explicit: Option<PathBuf>, chroot: Option<String>) -> Result<Self> {
22        let global = resolve_global(explicit)?;
23        let effective = match &chroot {
24            Some(name) => {
25                validate_chroot_name(name)?;
26                global.join(CHROOTS).join(name)
27            }
28            None => global.clone(),
29        };
30        Ok(Self {
31            global,
32            effective,
33            chroot,
34        })
35    }
36
37    /// Directory used by put/get/send/poll and other data commands.
38    pub fn path(&self) -> &Path {
39        &self.effective
40    }
41
42    /// Top-level store (parent of `chroots/`).
43    pub fn global_path(&self) -> &Path {
44        &self.global
45    }
46
47    pub fn chroot_name(&self) -> Option<&str> {
48        self.chroot.as_deref()
49    }
50
51    pub fn ensure(&self) -> Result<()> {
52        std::fs::create_dir_all(self.path())?;
53        Ok(())
54    }
55}
56
57fn resolve_global(explicit: Option<PathBuf>) -> Result<PathBuf> {
58    if let Some(p) = explicit {
59        return Ok(p);
60    }
61    if let Ok(p) = std::env::var("UNIFIER_HOME") {
62        return Ok(PathBuf::from(p));
63    }
64    let base = user_home()?.join(".local");
65    Ok(base.join(APP))
66}
67
68fn user_home() -> Result<PathBuf> {
69    std::env::var_os("HOME")
70        .or_else(|| std::env::var_os("USERPROFILE"))
71        .map(PathBuf::from)
72        .ok_or_else(|| crate::Error::msg("could not resolve home directory"))
73}