Skip to main content

actr_config/user_config/
loader.rs

1//! Shared user configuration file loader.
2
3use super::schema::CliConfig;
4use crate::error::{ConfigError, Result};
5use std::path::{Path, PathBuf};
6
7/// Returns the path to the global user-level config file: `~/.actr/config.toml`.
8pub fn global_config_path() -> Result<PathBuf> {
9    let home = dirs::home_dir().ok_or_else(|| {
10        ConfigError::InvalidConfig("Unable to determine home directory".to_string())
11    })?;
12    Ok(home.join(".actr").join("config.toml"))
13}
14
15/// Returns the path to the local project-level config file: `.actr/config.toml`.
16pub fn local_config_path() -> PathBuf {
17    PathBuf::from(".actr").join("config.toml")
18}
19
20/// Load a user config from the given path.
21///
22/// Returns `None` if the file does not exist.
23/// Returns an error if the file exists but cannot be parsed or fails validation.
24pub fn load_cli_config(path: &Path) -> Result<Option<CliConfig>> {
25    let content = match std::fs::read_to_string(path) {
26        Ok(content) => content,
27        Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None),
28        Err(error) => {
29            return Err(ConfigError::InvalidConfig(format!(
30                "Failed to read {}: {}",
31                path.display(),
32                error
33            )));
34        }
35    };
36    let config: CliConfig = toml::from_str(&content).map_err(|error| {
37        ConfigError::InvalidConfig(format!("Failed to parse {}: {}", path.display(), error))
38    })?;
39    config.validate().map_err(|error| {
40        ConfigError::InvalidConfig(format!("Invalid config at {}: {}", path.display(), error))
41    })?;
42
43    Ok(Some(config))
44}