Skip to main content

confium_registry/
paths.rs

1//! Filesystem locations used by the CLI and the registry client.
2//!
3//! All paths are derived from the `XDG_*` / `HOME` environment so the
4//! behaviour matches `TODO.roadmap/07-cli-tools.md` (Configuration
5//! section) on POSIX systems:
6//!
7//! - config: `~/.config/confium/`
8//! - plugins: `~/.local/share/confium/plugins/`
9//!
10//! Each helper accepts an optional override root so tests can point the
11//! CLI at a temp directory without touching the real home. When the
12//! override is `None` the function falls back to the environment-derived
13//! path.
14
15use std::path::PathBuf;
16
17use crate::error::{Error, Result};
18
19/// The base config directory, honouring `XDG_CONFIG_HOME` then `$HOME`.
20///
21/// When `override_home` is supplied, the returned path is
22/// `<override_home>/.config/confium` — useful for tests.
23pub fn config_dir(override_home: Option<&PathBuf>) -> Result<PathBuf> {
24    if let Some(home) = override_home {
25        return Ok(home.join(".config").join("confium"));
26    }
27    if let Ok(xdg) = std::env::var("XDG_CONFIG_HOME") {
28        if !xdg.is_empty() {
29            return Ok(PathBuf::from(xdg).join("confium"));
30        }
31    }
32    Ok(home_dir()?.join(".config").join("confium"))
33}
34
35/// The base data directory for installed plugins.
36pub fn plugins_dir(override_home: Option<&PathBuf>) -> Result<PathBuf> {
37    if let Some(home) = override_home {
38        return Ok(home
39            .join(".local")
40            .join("share")
41            .join("confium")
42            .join("plugins"));
43    }
44    if let Ok(xdg) = std::env::var("XDG_DATA_HOME") {
45        if !xdg.is_empty() {
46            return Ok(PathBuf::from(xdg).join("confium").join("plugins"));
47        }
48    }
49    Ok(home_dir()?
50        .join(".local")
51        .join("share")
52        .join("confium")
53        .join("plugins"))
54}
55
56/// Where a single installed plugin artifact lives:
57/// `<plugins>/<name>-<version>.so`.
58pub fn plugin_install_dir(
59    override_home: Option<&PathBuf>,
60    name: &str,
61    version: &str,
62) -> Result<PathBuf> {
63    let file = format!("{name}-{version}.so");
64    Ok(plugins_dir(override_home)?.join(file))
65}
66
67/// The trust-store directory (`<config>/trust`).
68pub fn trust_dir(override_home: Option<&PathBuf>) -> Result<PathBuf> {
69    Ok(config_dir(override_home)?.join("trust"))
70}
71
72/// The main config file (`<config>/config.toml`).
73pub fn config_file(override_home: Option<&PathBuf>) -> Result<PathBuf> {
74    Ok(config_dir(override_home)?.join("config.toml"))
75}
76
77fn home_dir() -> Result<PathBuf> {
78    std::env::var("HOME")
79        .map(PathBuf::from)
80        .map_err(|_| Error::InvalidPath {
81            path: "HOME is not set".to_string(),
82        })
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn config_dir_honours_override() {
91        let home = PathBuf::from("/tmp/fake-home");
92        let got = config_dir(Some(&home)).unwrap();
93        assert_eq!(got, PathBuf::from("/tmp/fake-home/.config/confium"));
94    }
95
96    #[test]
97    fn plugins_dir_honours_override() {
98        let home = PathBuf::from("/tmp/fake-home");
99        let got = plugins_dir(Some(&home)).unwrap();
100        assert_eq!(
101            got,
102            PathBuf::from("/tmp/fake-home/.local/share/confium/plugins")
103        );
104    }
105
106    #[test]
107    fn plugin_install_dir_combines_name_version() {
108        let home = PathBuf::from("/tmp/fake-home");
109        let got = plugin_install_dir(Some(&home), "botan", "3.2.0").unwrap();
110        assert_eq!(
111            got,
112            PathBuf::from("/tmp/fake-home/.local/share/confium/plugins/botan-3.2.0.so")
113        );
114    }
115
116    #[test]
117    fn trust_dir_under_config() {
118        let home = PathBuf::from("/tmp/fake-home");
119        let got = trust_dir(Some(&home)).unwrap();
120        assert_eq!(got, PathBuf::from("/tmp/fake-home/.config/confium/trust"));
121    }
122}