#![cfg_attr(coverage_nightly, coverage(off))]
use super::hooks_command::HooksCommand;
use super::tdg_hooks::install_tdg_hooks_wrapper;
use super::types::{HookStatus, HookVerificationResult};
use crate::cli::colors as c;
use crate::cli::commands::HooksCommands;
use anyhow::Result;
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn handle_hooks_command(cmd: &HooksCommands) -> Result<()> {
let hooks_cmd = HooksCommand::for_current_repo()?;
match cmd {
HooksCommands::Init {
interactive,
force,
backup,
tdg_enforcement,
} => handle_install(&hooks_cmd, *force, *backup, *interactive, *tdg_enforcement).await,
HooksCommands::Install {
interactive,
force,
backup,
tdg_enforcement,
stack,
update,
} => {
if *stack {
return crate::cli::handlers::hooks_stack_handler::handle_hooks_install_stack(
*update,
)
.await;
}
handle_install(&hooks_cmd, *force, *backup, *interactive, *tdg_enforcement).await
}
HooksCommands::Uninstall { restore_backup } => {
handle_uninstall(&hooks_cmd, *restore_backup).await
}
HooksCommands::Status { stack, format } => {
if *stack {
return crate::cli::handlers::hooks_stack_handler::handle_hooks_status_stack(
format,
)
.await;
}
handle_status(&hooks_cmd).await
}
HooksCommands::Verify { fix } => handle_verify(&hooks_cmd, *fix).await,
HooksCommands::Refresh => handle_refresh(&hooks_cmd).await,
HooksCommands::Run {
all_files,
verbose,
cache,
} => handle_run(&hooks_cmd, *all_files, *verbose, *cache).await,
HooksCommands::Cache { action } => super::cache_handlers::handle_cache(action).await,
}
}
async fn handle_install(
hooks_cmd: &HooksCommand,
force: bool,
backup: bool,
interactive: bool,
tdg_enforcement: bool,
) -> Result<()> {
if tdg_enforcement {
println!(
"{}",
c::label("Installing PMAT hooks with TDG enforcement...")
);
return install_tdg_hooks_wrapper().await;
}
println!("{}", c::label("Installing pre-commit hooks..."));
if interactive {
println!(" {}", c::dim("Interactive mode enabled"));
}
if force {
println!(" {}", c::dim("Force installation enabled"));
}
let result = hooks_cmd.install(force, backup, interactive).await?;
if result.success {
if result.backup_created {
println!(
" {} Backup created: {}",
c::pass(""),
c::path(".git/hooks/pre-commit.pmat-backup")
);
}
println!("{}", c::pass(&result.message));
} else {
println!("{}", c::fail(&result.message));
return Err(anyhow::anyhow!(result.message));
}
Ok(())
}
async fn handle_uninstall(hooks_cmd: &HooksCommand, restore_backup: bool) -> Result<()> {
println!("{}", c::label("Uninstalling pre-commit hooks..."));
if restore_backup {
println!(" {}", c::dim("Restoring backup enabled"));
}
let result = hooks_cmd.uninstall(restore_backup).await?;
if result.success {
if result.backup_restored {
println!(" {}", c::pass("Backup restored"));
}
println!("{}", c::pass(&result.message));
} else {
println!("{}", c::fail(&result.message));
return Err(anyhow::anyhow!(result.message));
}
Ok(())
}
async fn handle_status(hooks_cmd: &HooksCommand) -> Result<()> {
let status = hooks_cmd.status().await?;
println!("{}", c::header("Pre-commit Hook Status:"));
println!(
" {}: {}",
c::dim("Installed"),
if status.installed {
c::pass("Yes")
} else {
c::fail("No")
}
);
if status.installed {
print_installed_status(&status);
}
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn print_installed_status(status: &HookStatus) {
println!(
" {}: {}",
c::dim("PMAT-managed"),
if status.is_pmat_managed {
c::pass("Yes")
} else {
c::fail("No")
}
);
println!(
" {}: {}",
c::dim("Config up-to-date"),
if status.config_up_to_date {
c::pass("Yes")
} else {
c::warn("No")
}
);
if let Some(last_updated) = &status.last_updated {
println!(" {}: {last_updated}", c::dim("Last updated"));
}
if let Some(preview) = &status.hook_content_preview {
println!("\n {}:", c::dim("Hook preview"));
for line in preview.lines() {
println!(" {}", c::dim(line));
}
}
}
async fn handle_verify(hooks_cmd: &HooksCommand, fix: bool) -> Result<()> {
println!("{}", c::label("Verifying pre-commit hooks..."));
if fix {
println!(" {}", c::dim("Auto-fix enabled"));
}
let result = hooks_cmd.verify(fix).await?;
print_verification_issues(&result);
print_verification_fixes(&result);
if result.is_valid {
println!("{}", c::pass("Pre-commit hooks verified successfully"));
} else {
println!("{}", c::fail("Pre-commit hooks verification failed"));
if !fix {
println!(
" {}",
c::dim("Run with --fix to attempt automatic repairs")
);
}
return Err(anyhow::anyhow!("Hook verification failed"));
}
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn print_verification_issues(result: &HookVerificationResult) {
if !result.issues.is_empty() {
println!(" {}:", c::subheader("Issues found"));
for issue in &result.issues {
println!(" {}", c::warn(issue));
}
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn print_verification_fixes(result: &HookVerificationResult) {
if !result.fixes_applied.is_empty() {
println!(" {}:", c::subheader("Fixes applied"));
for fix_msg in &result.fixes_applied {
println!(" {}", c::pass(fix_msg));
}
}
}
async fn handle_refresh(hooks_cmd: &HooksCommand) -> Result<()> {
println!(
"{}",
c::label("Refreshing pre-commit hooks from configuration...")
);
let result = hooks_cmd.refresh().await?;
if result.success {
if result.config_changes_detected {
println!(" {}", c::pass("Configuration changes detected"));
}
if result.hook_updated {
println!(" {}", c::pass("Hook updated with new configuration"));
}
println!("{}", c::pass(&result.message));
} else {
println!("{}", c::fail(&result.message));
return Err(anyhow::anyhow!(result.message));
}
Ok(())
}
async fn handle_run(
hooks_cmd: &HooksCommand,
all_files: bool,
verbose: bool,
use_cache: bool,
) -> Result<()> {
let start_time = std::time::Instant::now();
if use_cache {
let project_root = std::env::current_dir()?;
let cache_manager = crate::tdg::hooks_cache::HooksCacheManager::new(&project_root);
if !project_root.join(".pmat/hooks-cache").exists() {
let _ = cache_manager.init();
}
match cache_manager.check() {
Ok(crate::tdg::hooks_cache::CacheCheckResult::Hit { result, cached_at }) => {
let elapsed = start_time.elapsed();
if verbose {
println!("{} O(1) Cache HIT - Skipping full analysis", c::pass(""));
println!(" {}: {:?}", c::dim("Cached result"), result);
println!(
" {}: {}",
c::dim("Cached at"),
cached_at.format("%Y-%m-%d %H:%M:%S UTC")
);
println!(
" {}: {:.2}ms",
c::dim("Check time"),
elapsed.as_secs_f64() * 1000.0
);
}
let _ = cache_manager.record_run(true, elapsed.as_millis() as u64);
match result {
crate::tdg::hooks_cache::CacheResult::Pass => {
println!(
"{} {}",
c::pass("All quality gates passed"),
c::dim("(cached)")
);
return Ok(());
}
crate::tdg::hooks_cache::CacheResult::Fail => {
println!("{} {}", c::fail("Quality gates failed"), c::dim("(cached)"));
return Err(anyhow::anyhow!("Pre-commit checks failed (cached)"));
}
crate::tdg::hooks_cache::CacheResult::Warn => {
println!(
"{} {}",
c::warn("Quality gates passed with warnings"),
c::dim("(cached)")
);
return Ok(());
}
}
}
Ok(crate::tdg::hooks_cache::CacheCheckResult::Miss { reason }) => {
if verbose {
println!("{} Cache MISS: {}", c::dim(""), reason);
println!(" {}", c::dim("Running full analysis..."));
}
}
Ok(crate::tdg::hooks_cache::CacheCheckResult::Partial { .. }) => {
if verbose {
println!(
"{}",
c::warn("Partial cache hit - running remaining gates...")
);
}
}
Err(e) => {
if verbose {
println!("{}", c::warn(&format!("Cache check failed: {}", e)));
println!(" {}", c::dim("Running full analysis..."));
}
}
}
}
let result = hooks_cmd.run(all_files, verbose).await?;
let elapsed = start_time.elapsed();
if verbose {
println!();
println!("{}", c::subheader("Results:"));
println!(
" {}: {}",
c::dim("Checks passed"),
c::number(&result.checks_passed.to_string())
);
println!(
" {}: {}",
c::dim("Checks failed"),
if result.checks_failed > 0 {
format!("{}{}{}", c::RED, result.checks_failed, c::RESET)
} else {
result.checks_failed.to_string()
}
);
println!(
" {}: {:.2}ms",
c::dim("Duration"),
elapsed.as_secs_f64() * 1000.0
);
println!();
println!("{}:", c::dim("Output"));
println!("{}", result.output);
} else {
println!("{}", result.output);
}
if use_cache {
let project_root = std::env::current_dir()?;
let cache_manager = crate::tdg::hooks_cache::HooksCacheManager::new(&project_root);
let cache_result = if result.success {
crate::tdg::hooks_cache::CacheResult::Pass
} else {
crate::tdg::hooks_cache::CacheResult::Fail
};
if let Err(e) = cache_manager.update(cache_result, std::collections::HashMap::new()) {
if verbose {
println!("{}", c::warn(&format!("Failed to update cache: {}", e)));
}
}
let _ = cache_manager.record_run(false, elapsed.as_millis() as u64);
}
if result.success {
println!();
println!("{}", c::pass("All pre-commit checks passed"));
Ok(())
} else {
println!();
println!("{}", c::fail("Pre-commit checks failed"));
Err(anyhow::anyhow!("Pre-commit checks failed"))
}
}