use std::path::{Path, PathBuf};
use crate::validation::{AndonSignal, AndonContext};
use super::path_protector::{PathProtector, PathProtectionError};
pub struct GeneratorPathGuard {
protector: PathProtector,
}
impl GeneratorPathGuard {
pub fn new(protector: PathProtector) -> Self {
Self { protector }
}
pub fn default() -> Self {
Self {
protector: PathProtector::default_protection(),
}
}
pub fn verify_write_path(&self, path: &Path) -> Result<AndonSignal, AndonContext> {
match self.protector.can_write(path) {
Ok(()) => {
let signal = if self.protector.is_regeneratable(path) {
AndonSignal::Green
} else {
AndonSignal::Yellow
};
Ok(signal)
}
Err(PathProtectionError::ProtectedPathViolation { path: p, pattern }) => {
Err(AndonContext::red(
format!(
"Protected path violation: '{}' matches protected pattern '{}'",
p, pattern
),
"PathGuard::verify_write_path",
))
}
}
}
pub fn verify_output_paths(&self, paths: &[PathBuf]) -> Result<(), AndonContext> {
for path in paths {
match self.verify_write_path(path) {
Ok(AndonSignal::Green) => continue,
Ok(AndonSignal::Yellow) => {
eprintln!("⚠️ YELLOW: {} - Not explicitly regeneratable", path.display());
continue;
}
Ok(AndonSignal::Red) | Err(_) => {
return Err(AndonContext::red(
format!("Cannot write to protected path: {}", path.display()),
"PathGuard::verify_output_paths",
))
}
}
}
Ok(())
}
pub fn protector(&self) -> &PathProtector {
&self.protector
}
pub fn is_protected(&self, path: &Path) -> bool {
self.protector.is_protected(path)
}
pub fn is_regeneratable(&self, path: &Path) -> bool {
self.protector.is_regeneratable(path)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn test_generator_guard_blocks_protected() {
let guard = GeneratorPathGuard::default();
let result = guard.verify_write_path(Path::new(".env"));
assert!(result.is_err());
}
#[test]
fn test_generator_guard_allows_regeneratable() {
let guard = GeneratorPathGuard::default();
let result = guard.verify_write_path(Path::new("src/main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), AndonSignal::Green);
}
#[test]
fn test_verify_multiple_paths() {
let guard = GeneratorPathGuard::default();
let paths = vec![
PathBuf::from("src/main.rs"),
PathBuf::from("mod.rs"),
];
assert!(guard.verify_output_paths(&paths).is_ok());
}
#[test]
fn test_verify_paths_with_protected() {
let guard = GeneratorPathGuard::default();
let paths = vec![
PathBuf::from("src/main.rs"),
PathBuf::from(".env"),
];
assert!(guard.verify_output_paths(&paths).is_err());
}
}