use std::{fs::{self}, path::PathBuf};
use serde::{Deserialize, Serialize};
fn default_true() -> bool {
true
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Config {
pub config_path: Option<PathBuf>,
pub watch_dir: PathBuf,
pub commit_delay_secs: u32,
#[serde(default = "default_true")]
pub auto_push: bool,
}
impl Config {
pub fn load(config_path: &str) -> Result<Config, Box<dyn std::error::Error>> {
let content = fs::read_to_string(config_path)?;
let user_config: Config = serde_yaml::from_str(&content)?;
Ok(user_config)
}
pub fn dump(&self) -> serde_yaml::Result<String> {
serde_yaml::to_string(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::NamedTempFile;
use std::io::Write;
#[test]
fn test_config_loading() {
let mut temp_file = NamedTempFile::new().unwrap();
writeln!(temp_file, r#"
watch_dir: "/tmp/test"
commit_delay_secs: 5
auto_push: false
"#).unwrap();
let config = Config::load(temp_file.path().to_str().unwrap()).unwrap();
assert_eq!(config.watch_dir, PathBuf::from("/tmp/test"));
assert_eq!(config.commit_delay_secs, 5);
assert!(!config.auto_push);
assert!(config.config_path.is_none());
}
#[test]
fn test_config_auto_push_defaults_to_true() {
let mut temp_file = NamedTempFile::new().unwrap();
writeln!(temp_file, r#"
watch_dir: "/home/user/project"
commit_delay_secs: 10
"#).unwrap();
let config = Config::load(temp_file.path().to_str().unwrap()).unwrap();
assert_eq!(config.watch_dir, PathBuf::from("/home/user/project"));
assert_eq!(config.commit_delay_secs, 10);
assert!(config.auto_push); assert!(config.config_path.is_none());
}
#[test]
fn test_config_with_optional_fields() {
let mut temp_file = NamedTempFile::new().unwrap();
writeln!(temp_file, r#"
watch_dir: "/home/user/project"
commit_delay_secs: 10
auto_push: false
config_path: "/etc/watchers.yml"
"#).unwrap();
let config = Config::load(temp_file.path().to_str().unwrap()).unwrap();
assert_eq!(config.watch_dir, PathBuf::from("/home/user/project"));
assert_eq!(config.commit_delay_secs, 10);
assert!(!config.auto_push);
assert_eq!(config.config_path, Some(PathBuf::from("/etc/watchers.yml")));
}
#[test]
fn test_config_dump() {
let config = Config {
watch_dir: PathBuf::from("/test/path"),
commit_delay_secs: 3,
auto_push: false,
config_path: Some(PathBuf::from("/config/path")),
};
let yaml_output = config.dump().unwrap();
assert!(yaml_output.contains("watch_dir: /test/path"));
assert!(yaml_output.contains("commit_delay_secs: 3"));
assert!(yaml_output.contains("auto_push: false"));
assert!(yaml_output.contains("config_path: /config/path"));
}
#[test]
fn test_config_invalid_file() {
let result = Config::load("/nonexistent/file.yml");
assert!(result.is_err());
}
#[test]
fn test_config_invalid_yaml() {
let mut temp_file = NamedTempFile::new().unwrap();
writeln!(temp_file, "invalid: yaml: content: [").unwrap();
let result = Config::load(temp_file.path().to_str().unwrap());
assert!(result.is_err());
}
}