pub mod bypass_cmd;
pub mod config_cmd;
pub mod hooks;
pub mod report_cmd;
pub mod stats_cmd;
pub mod status;
use crate::Result;
use crate::commands::SafetyBypassStage;
use crate::safety::{PipelineStage, SafetyPipeline, bypass::BypassManager, config::BypassConfig};
use console::style;
use std::path::Path;
pub async fn handle_install(force: bool, project_path: &Path, install_cargo: bool) -> Result<()> {
hooks::display_install_header();
let hooks_dir = hooks::validate_git_repo_and_create_hooks_dir(project_path)?;
hooks::install_pre_commit_hook(&hooks_dir, force)?;
hooks::install_pre_push_hook(&hooks_dir, force)?;
if install_cargo {
hooks::install_cargo_interception(force)?;
}
hooks::display_install_success(install_cargo);
Ok(())
}
pub async fn handle_check(stage_str: &str, project_path: &Path, verbose: bool) -> Result<()> {
let stage = stage_str.parse::<PipelineStage>()?;
println!("🧪 Testing Safety Pipeline - {}", stage.display_name());
println!("{}", "=".repeat(50));
let pipeline = SafetyPipeline::new(project_path).await?;
let report = pipeline.run_checks(stage).await?;
if verbose {
report.print_detailed();
} else {
report.print_summary();
}
if !report.passed {
println!(
"\n{}",
style("⚠️ This operation would be BLOCKED by the safety pipeline")
.red()
.bold()
);
println!("Fix the issues above before committing/pushing/publishing");
} else {
println!(
"\n{}",
style("✅ This operation would be ALLOWED by the safety pipeline")
.green()
.bold()
);
}
Ok(())
}
pub async fn handle_status() -> Result<()> {
status::display_status_header();
status::display_safety_configuration().await;
status::display_git_hooks_status();
Ok(())
}
pub async fn test_individual_checks(project_path: &Path) -> Result<()> {
crate::safety::checks::test_runner::test_safety_checks(project_path).await
}
pub async fn handle_check_bypass(stage: SafetyBypassStage) -> Result<()> {
let pipeline_stage = stage.to_pipeline_stage();
let config = BypassConfig::load_or_default().await?;
if !config.enabled {
std::process::exit(1);
}
let manager = BypassManager::new(&config)?;
match manager.check_active_bypass(pipeline_stage).await? {
Some(_) => {
println!("active");
Ok(())
}
None => {
std::process::exit(1);
}
}
}
pub async fn handle_uninstall(project_path: &Path, confirm: bool) -> Result<()> {
if !confirm {
println!("⚠️ This will remove all Ferrous Forge safety hooks.");
println!(" Run with --confirm to proceed.");
return Ok(());
}
hooks::uninstall_hooks(project_path)
}