Skip to main content

sniff/
config_loader.rs

1use crate::config::ResolvedConfig;
2use crate::env_value;
3use std::fs;
4use std::path::{Path, PathBuf};
5
6fn find_config_path(cwd: &Path) -> Option<PathBuf> {
7    let mut current_dir = cwd.to_path_buf();
8    loop {
9        let potential = current_dir.join("sniff.config.toml");
10        if potential.is_file() {
11            return Some(potential);
12        }
13        if !current_dir.pop() {
14            break;
15        }
16    }
17    None
18}
19
20pub fn resolve_config(cwd: &Path) -> Result<ResolvedConfig, String> {
21    let mut config = ResolvedConfig::default();
22
23    if let Some(config_path) = find_config_path(cwd) {
24        let content = fs::read_to_string(&config_path)
25            .map_err(|err| format!("failed to read config {}: {}", config_path.display(), err))?;
26        config = toml::from_str::<ResolvedConfig>(&content)
27            .map_err(|err| format!("failed to parse config {}: {}", config_path.display(), err))?;
28    }
29
30    if let Some(model) = env_value::read("SNIFF_MODEL") {
31        config.model = model;
32    }
33
34    if let Some(endpoint) = env_value::read("SNIFF_ENDPOINT") {
35        config.llm.endpoint = endpoint;
36    }
37
38    Ok(config)
39}
40
41#[cfg(test)]
42mod tests {
43    use super::resolve_config;
44    use std::fs;
45    use std::time::{SystemTime, UNIX_EPOCH};
46
47    #[test]
48    fn invalid_config_fails_instead_of_using_defaults() {
49        let unique = SystemTime::now()
50            .duration_since(UNIX_EPOCH)
51            .unwrap()
52            .as_nanos();
53        let root = std::env::temp_dir().join(format!("sniff-invalid-config-{unique}"));
54        fs::create_dir_all(&root).unwrap();
55        fs::write(root.join("sniff.config.toml"), "[thresholds\ninvalid").unwrap();
56
57        let err = resolve_config(&root).expect_err("invalid config should fail explicitly");
58        assert!(err.contains("failed to parse config"), "{err}");
59
60        let _ = fs::remove_dir_all(&root);
61    }
62}