use crate::config::types::Configuration;
use crate::config::ConfigError;
use std::collections::HashSet;
pub fn validate_required_fields(config: &Configuration) -> Result<(), ConfigError> {
if config.version.is_empty() {
return Err(ConfigError::MissingField {
field: "version".to_string(),
});
}
if config.environments.is_empty() {
return Err(ConfigError::MissingField {
field: "environments".to_string(),
});
}
for (env_name, env) in &config.environments {
if env.description.is_empty() {
return Err(ConfigError::ValidationError {
message: format!(
"Environment '{}' must have a non-empty description",
env_name
),
});
}
}
Ok(())
}
pub fn validate_environment_references(config: &Configuration) -> Result<(), ConfigError> {
let env_names: HashSet<&String> = config.environments.keys().collect();
for env in config.environments.values() {
if let Some(extends) = &env.extends {
if !env_names.contains(&extends) {
return Err(ConfigError::InvalidEnvironment {
name: extends.clone(),
});
}
}
}
Ok(())
}
pub fn validate_no_circular_references(config: &Configuration) -> Result<(), ConfigError> {
for env_name in config.environments.keys() {
let mut visited = HashSet::new();
let mut path = Vec::new();
if detect_circular_reference(config, env_name, &mut visited, &mut path)? {
return Err(ConfigError::CircularReference { cycle: path });
}
}
Ok(())
}
fn detect_circular_reference(
config: &Configuration,
current: &str,
visited: &mut HashSet<String>,
path: &mut Vec<String>,
) -> Result<bool, ConfigError> {
if path.contains(¤t.to_string()) {
path.push(current.to_string());
return Ok(true);
}
if visited.contains(current) {
return Ok(false);
}
visited.insert(current.to_string());
path.push(current.to_string());
if let Some(env) = config.environments.get(current) {
if let Some(extends) = &env.extends {
if detect_circular_reference(config, extends, visited, path)? {
return Ok(true);
}
}
}
path.pop();
Ok(false)
}
pub fn validate_common_config(config: &Configuration) -> Result<(), ConfigError> {
if let Some(common) = &config.common {
for (key, value) in common {
if key.is_empty() {
return Err(ConfigError::ValidationError {
message: "Common variable keys cannot be empty".to_string(),
});
}
if value.is_empty() {
return Err(ConfigError::ValidationError {
message: format!("Common variable '{}' cannot have empty value", key),
});
}
}
}
Ok(())
}