use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use crate::error::SaraError;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Config {
#[serde(default)]
pub repositories: RepositoryConfig,
#[serde(default)]
pub validation: ValidationConfig,
#[serde(default)]
pub output: OutputConfig,
#[serde(default)]
pub templates: TemplatesConfig,
}
impl Config {
pub fn new() -> Self {
Self::default()
}
pub fn add_repository(&mut self, path: impl Into<PathBuf>) {
self.repositories.paths.push(path.into());
}
pub fn expand_template_paths(&self) -> Result<Vec<PathBuf>, SaraError> {
let mut result = Vec::new();
for pattern in &self.templates.paths {
match glob::glob(pattern) {
Ok(paths) => {
for entry in paths {
match entry {
Ok(path) => result.push(path),
Err(e) => {
return Err(SaraError::InvalidGlobPattern {
pattern: pattern.clone(),
reason: e.to_string(),
});
}
}
}
}
Err(e) => {
return Err(SaraError::InvalidGlobPattern {
pattern: pattern.clone(),
reason: e.to_string(),
});
}
}
}
Ok(result)
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct RepositoryConfig {
#[serde(default)]
pub paths: Vec<PathBuf>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ValidationConfig {
#[serde(default)]
pub strict_mode: bool,
#[serde(default)]
pub allowed_custom_fields: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutputConfig {
#[serde(default = "default_true")]
pub colors: bool,
#[serde(default = "default_true")]
pub emojis: bool,
}
impl Default for OutputConfig {
fn default() -> Self {
Self {
colors: true,
emojis: true,
}
}
}
fn default_true() -> bool {
true
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TemplatesConfig {
#[serde(default)]
pub paths: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = Config::default();
assert!(config.repositories.paths.is_empty());
assert!(!config.validation.strict_mode);
assert!(config.output.colors);
assert!(config.output.emojis);
}
#[test]
fn test_add_repository() {
let mut config = Config::default();
config.add_repository("/path/to/repo");
assert_eq!(config.repositories.paths.len(), 1);
}
#[test]
fn test_config_serialization() {
let config = Config::default();
let toml_str = toml::to_string(&config).unwrap();
assert!(toml_str.contains("[repositories]"));
}
}