use adrs_core::{IssueSeverity, Repository, check_all_filtered};
use anyhow::{Context, Result};
use std::path::Path;
pub fn doctor(root: &Path, ng: bool, ignore: Vec<String>, warnings_as_errors: bool) -> Result<()> {
if ng {
eprintln!(
"note: --ng has no effect on 'doctor'; lint rules detect each ADR's format automatically"
);
}
let repo =
Repository::open(root).context("Failed to open repository. Have you run 'adrs init'?")?;
let (report, suppressed_count, config_warnings) =
check_all_filtered(&repo, &ignore).context("Failed to run health checks")?;
for warning in &config_warnings {
eprintln!("warning: {warning}");
}
let warnings_as_errors = warnings_as_errors || repo.config().doctor.warnings_as_errors;
if report.issues.is_empty() {
println!("No issues found. Your ADR repository is healthy!");
if suppressed_count > 0 {
println!("{} issue(s) suppressed by ignore rules", suppressed_count);
}
return Ok(());
}
let error_count = report.count_by_severity(IssueSeverity::Error);
let warning_count = report.count_by_severity(IssueSeverity::Warning);
let info_count = report.count_by_severity(IssueSeverity::Info);
for issue in &report.issues {
let prefix = match issue.severity {
IssueSeverity::Error => "error",
IssueSeverity::Warning => "warning",
IssueSeverity::Info => "info",
};
let location = match (&issue.path, issue.line, issue.adr_number) {
(Some(path), Some(line), _) => {
format!(" [{}:{}]", path.display(), line)
}
(Some(path), None, _) => format!(" [{}]", path.display()),
(None, _, Some(num)) => format!(" [ADR {}]", num),
_ => String::new(),
};
println!(
"{}: [{}] {}{}",
prefix, issue.rule_id, issue.message, location
);
}
println!();
println!(
"Found {} error(s), {} warning(s), {} info(s)",
error_count, warning_count, info_count
);
if suppressed_count > 0 {
println!("{} issue(s) suppressed by ignore rules", suppressed_count);
}
if report.has_errors() || (warnings_as_errors && report.has_warnings()) {
std::process::exit(1);
}
Ok(())
}