vespertide_loader/
config.rs1use std::fs;
2use std::path::{Path, PathBuf};
3
4use anyhow::{Context, Result};
5use vespertide_config::VespertideConfig;
6
7fn read_config(path: &Path) -> Result<VespertideConfig> {
9 let content = fs::read_to_string(path).context("read vespertide.json")?;
10 let config: VespertideConfig =
11 serde_json::from_str(&content).context("parse vespertide.json")?;
12 Ok(config)
13}
14
15pub fn load_config() -> Result<VespertideConfig> {
17 let path = PathBuf::from("vespertide.json");
18 if !path.exists() {
19 anyhow::bail!("vespertide.json not found. Run 'vespertide init' first.");
20 }
21
22 read_config(&path)
23}
24
25pub fn load_config_from_path(path: impl AsRef<Path>) -> Result<VespertideConfig> {
27 let path = path.as_ref();
28 if !path.exists() {
29 anyhow::bail!("vespertide.json not found at: {}", path.display());
30 }
31
32 read_config(path)
33}
34
35pub fn load_config_or_default(project_root: Option<PathBuf>) -> Result<VespertideConfig> {
37 let config_path = if let Some(root) = project_root {
38 root.join("vespertide.json")
39 } else {
40 PathBuf::from("vespertide.json")
41 };
42
43 if config_path.exists() {
44 load_config_from_path(config_path)
45 } else {
46 Ok(VespertideConfig::default())
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use crate::test_support::{CwdGuard, write_default_config};
54 use serial_test::serial;
55 use tempfile::tempdir;
56
57 #[test]
58 #[serial]
59 fn test_load_config_from_path_success() {
60 let tmp = tempdir().unwrap();
61 let config_path = tmp.path().join("vespertide.json");
62 write_default_config(&config_path);
63
64 let result = load_config_from_path(config_path);
65 assert!(result.is_ok());
66 let config = result.unwrap();
67 assert_eq!(config.models_dir, PathBuf::from("models"));
68 }
69
70 #[test]
71 #[serial]
72 fn test_load_config_from_path_not_found() {
73 let tmp = tempdir().unwrap();
74 let config_path = tmp.path().join("nonexistent.json");
75
76 let result = load_config_from_path(config_path.clone());
77 assert!(result.is_err());
78 let err_msg = result.unwrap_err().to_string();
79 assert!(err_msg.contains("vespertide.json not found at:"));
80 assert!(err_msg.contains(&config_path.display().to_string()));
81 }
82
83 #[test]
84 #[serial]
85 fn test_load_config_or_default_with_root() {
86 let tmp = tempdir().unwrap();
87 let config_path = tmp.path().join("vespertide.json");
88 write_default_config(&config_path);
89
90 let result = load_config_or_default(Some(tmp.path().to_path_buf()));
91 assert!(result.is_ok());
92 let config = result.unwrap();
93 assert_eq!(config.models_dir, PathBuf::from("models"));
94 }
95
96 #[test]
97 #[serial]
98 fn test_load_config_or_default_without_root() {
99 let tmp = tempdir().unwrap();
100 let _guard = CwdGuard::new(tmp.path());
101 let config_path = PathBuf::from("vespertide.json");
102 write_default_config(&config_path);
103
104 let result = load_config_or_default(None);
105 assert!(result.is_ok());
106 let config = result.unwrap();
107 assert_eq!(config.models_dir, PathBuf::from("models"));
108 }
109
110 #[test]
111 #[serial]
112 fn test_load_config_or_default_fallback_to_default() {
113 let tmp = tempdir().unwrap();
114 let _guard = CwdGuard::new(tmp.path());
115
116 let result = load_config_or_default(None);
117 assert!(result.is_ok());
118 let config = result.unwrap();
119 assert_eq!(config.models_dir, PathBuf::from("models"));
120 }
121
122 #[test]
123 #[serial]
124 fn test_load_config_success() {
125 let tmp = tempdir().unwrap();
126 let _guard = CwdGuard::new(tmp.path());
127 let config_path = PathBuf::from("vespertide.json");
128 write_default_config(&config_path);
129
130 let result = load_config();
131 assert!(result.is_ok());
132 let config = result.unwrap();
133 assert_eq!(config.models_dir, PathBuf::from("models"));
134 }
135
136 #[test]
137 #[serial]
138 fn test_load_config_not_found() {
139 let tmp = tempdir().unwrap();
140 let _guard = CwdGuard::new(tmp.path());
141
142 let result = load_config();
143 assert!(result.is_err());
144 let err_msg = result.unwrap_err().to_string();
145 assert!(err_msg.contains("vespertide.json not found"));
146 }
147}