Skip to main content

cc_audit/config/
loading.rs

1//! Configuration loading functions.
2
3use std::fs;
4use std::path::Path;
5
6use super::error::ConfigError;
7use super::types::Config;
8
9impl Config {
10    /// Load configuration from a file.
11    pub fn from_file(path: &Path) -> Result<Self, ConfigError> {
12        let content = fs::read_to_string(path).map_err(|e| ConfigError::ReadFile {
13            path: path.display().to_string(),
14            source: e,
15        })?;
16
17        let ext = path
18            .extension()
19            .and_then(|e| e.to_str())
20            .unwrap_or("")
21            .to_lowercase();
22
23        match ext.as_str() {
24            "yaml" | "yml" => serde_yaml::from_str(&content).map_err(|e| ConfigError::ParseYaml {
25                path: path.display().to_string(),
26                source: e,
27            }),
28            "json" => serde_json::from_str(&content).map_err(|e| ConfigError::ParseJson {
29                path: path.display().to_string(),
30                source: e,
31            }),
32            "toml" => toml::from_str(&content).map_err(|e| ConfigError::ParseToml {
33                path: path.display().to_string(),
34                source: e,
35            }),
36            _ => Err(ConfigError::UnsupportedFormat(
37                path.display().to_string(),
38                ext,
39            )),
40        }
41    }
42
43    /// Load configuration from the project directory or global config.
44    ///
45    /// Search order:
46    /// 1. `.cc-audit.yaml` in project root
47    /// 2. `.cc-audit.json` in project root
48    /// 3. `.cc-audit.toml` in project root
49    /// 4. `~/.config/cc-audit/config.yaml`
50    /// 5. Default configuration
51    pub fn load(project_root: Option<&Path>) -> Self {
52        // Try project-level config files
53        if let Some(root) = project_root {
54            for filename in &[
55                ".cc-audit.yaml",
56                ".cc-audit.yml",
57                ".cc-audit.json",
58                ".cc-audit.toml",
59            ] {
60                let path = root.join(filename);
61                if path.exists()
62                    && let Ok(config) = Self::from_file(&path)
63                {
64                    return config;
65                }
66            }
67        }
68
69        // Try global config
70        if let Some(config_dir) = dirs::config_dir() {
71            let global_config = config_dir.join("cc-audit").join("config.yaml");
72            if global_config.exists()
73                && let Ok(config) = Self::from_file(&global_config)
74            {
75                return config;
76            }
77        }
78
79        // Return default
80        Self::default()
81    }
82}