plugin_packager/
config.rs1use anyhow::{Context, Result};
10use serde::{Deserialize, Serialize};
11use std::fs;
12use std::path::{Path, PathBuf};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct Config {
17 #[serde(default = "Config::default_plugin_dir")]
19 pub plugin_dir: PathBuf,
20
21 #[serde(default = "Config::default_registry_file")]
23 pub registry_file: PathBuf,
24
25 #[serde(default = "Config::default_verify_on_install")]
27 pub verify_on_install: bool,
28
29 #[serde(default = "Config::default_auto_register")]
31 pub auto_register: bool,
32
33 #[serde(default = "Config::default_check_dependencies")]
35 pub check_dependencies: bool,
36
37 #[serde(default = "Config::default_max_concurrent")]
39 pub max_concurrent_installs: usize,
40
41 #[serde(default = "Config::default_cache_dir")]
43 pub cache_dir: PathBuf,
44
45 #[serde(default = "Config::default_verbose")]
47 pub verbose: bool,
48
49 #[serde(default = "Config::default_backup_on_upgrade")]
51 pub backup_on_upgrade: bool,
52}
53
54impl Config {
55 fn default_plugin_dir() -> PathBuf {
57 let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("/tmp"));
58 home.join(".skylet").join("plugins")
59 }
60
61 fn default_registry_file() -> PathBuf {
63 let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("/tmp"));
64 home.join(".skylet").join("registry.json")
65 }
66
67 fn default_verify_on_install() -> bool {
69 true
70 }
71
72 fn default_auto_register() -> bool {
74 true
75 }
76
77 fn default_check_dependencies() -> bool {
79 false }
81
82 fn default_max_concurrent() -> usize {
84 4
85 }
86
87 fn default_cache_dir() -> PathBuf {
89 let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("/tmp"));
90 home.join(".skylet").join("cache")
91 }
92
93 fn default_verbose() -> bool {
95 false
96 }
97
98 fn default_backup_on_upgrade() -> bool {
100 true
101 }
102
103 pub fn load_or_default(path: &Path) -> Result<Self> {
105 if path.exists() {
106 Self::load(path)
107 } else {
108 Ok(Self::default())
109 }
110 }
111
112 pub fn load(path: &Path) -> Result<Self> {
114 let content = fs::read_to_string(path).context("reading config file")?;
115 let config: Self = toml::from_str(&content).context("parsing config file")?;
116 Ok(config)
117 }
118
119 pub fn save(&self, path: &Path) -> Result<()> {
121 let parent = path.parent();
122 if let Some(parent_path) = parent {
123 fs::create_dir_all(parent_path).context("creating config directory")?;
124 }
125
126 let content = toml::to_string_pretty(self).context("serializing config")?;
127 fs::write(path, content).context("writing config file")?;
128 Ok(())
129 }
130
131 pub fn config_path() -> Result<PathBuf> {
133 let home = dirs::home_dir().context("could not determine home directory")?;
134 let config_path = home.join(".skylet").join("config.toml");
135 Ok(config_path)
136 }
137
138 pub fn ensure_plugin_dir(&self) -> Result<()> {
140 fs::create_dir_all(&self.plugin_dir).context("failed to create plugin directory")?;
141 Ok(())
142 }
143
144 pub fn ensure_cache_dir(&self) -> Result<()> {
146 fs::create_dir_all(&self.cache_dir).context("failed to create cache directory")?;
147 Ok(())
148 }
149
150 pub fn ensure_registry_dir(&self) -> Result<()> {
152 if let Some(parent) = self.registry_file.parent() {
153 fs::create_dir_all(parent).context("failed to create registry directory")?;
154 }
155 Ok(())
156 }
157
158 pub fn ensure_all_dirs(&self) -> Result<()> {
160 self.ensure_plugin_dir()?;
161 self.ensure_cache_dir()?;
162 self.ensure_registry_dir()?;
163 Ok(())
164 }
165}
166
167impl Default for Config {
168 fn default() -> Self {
169 Self {
170 plugin_dir: Config::default_plugin_dir(),
171 registry_file: Config::default_registry_file(),
172 verify_on_install: Config::default_verify_on_install(),
173 auto_register: Config::default_auto_register(),
174 check_dependencies: Config::default_check_dependencies(),
175 max_concurrent_installs: Config::default_max_concurrent(),
176 cache_dir: Config::default_cache_dir(),
177 verbose: Config::default_verbose(),
178 backup_on_upgrade: Config::default_backup_on_upgrade(),
179 }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186 use tempfile::tempdir;
187
188 #[test]
189 fn test_config_default() {
190 let config = Config::default();
191 assert!(config.verify_on_install);
192 assert!(config.auto_register);
193 assert!(!config.check_dependencies);
194 assert_eq!(config.max_concurrent_installs, 4);
195 assert!(!config.verbose);
196 assert!(config.backup_on_upgrade);
197 }
198
199 #[test]
200 fn test_config_save_and_load() -> Result<()> {
201 let temp_dir = tempdir()?;
202 let config_path = temp_dir.path().join("config.toml");
203
204 let mut config = Config::default();
206 config.verbose = true;
207 config.max_concurrent_installs = 8;
208 config.check_dependencies = true;
209
210 config.save(&config_path)?;
212 assert!(config_path.exists());
213
214 let loaded = Config::load(&config_path)?;
216 assert_eq!(loaded.verbose, true);
217 assert_eq!(loaded.max_concurrent_installs, 8);
218 assert_eq!(loaded.check_dependencies, true);
219
220 Ok(())
221 }
222
223 #[test]
224 fn test_config_load_or_default() -> Result<()> {
225 let temp_dir = tempdir()?;
226 let config_path = temp_dir.path().join("nonexistent.toml");
227
228 let config = Config::load_or_default(&config_path)?;
230 assert_eq!(config.max_concurrent_installs, 4);
231
232 Ok(())
233 }
234
235 #[test]
236 fn test_config_ensure_dirs() -> Result<()> {
237 let temp_dir = tempdir()?;
238 let mut config = Config::default();
239 config.plugin_dir = temp_dir.path().join("plugins");
240 config.cache_dir = temp_dir.path().join("cache");
241 config.registry_file = temp_dir.path().join("registry.json");
242
243 config.ensure_all_dirs()?;
244
245 assert!(config.plugin_dir.exists());
246 assert!(config.cache_dir.exists());
247
248 Ok(())
249 }
250
251 #[test]
252 fn test_config_toml_serialization() -> Result<()> {
253 let config = Config::default();
254 let toml_str = toml::to_string_pretty(&config)?;
255
256 assert!(toml_str.contains("plugin_dir"));
258 assert!(toml_str.contains("registry_file"));
259 assert!(toml_str.contains("verify_on_install"));
260
261 Ok(())
262 }
263}