1use crate::doctor::{run_doctor, DoctorCheck, DoctorStatus};
2use crate::error::Result;
3use crate::git::{CliOps, GitOps};
4
5use super::util::find_git_dir;
6
7pub fn run(json: bool, staleness: bool) -> Result<()> {
9 let git_dir = find_git_dir()?;
10 let repo_dir = git_dir.parent().unwrap_or(&git_dir).to_path_buf();
11 let git_ops = CliOps::new(repo_dir);
12
13 let mut report = run_doctor(&git_ops, &git_dir)?;
14
15 if staleness {
16 let staleness_check = check_staleness(&git_ops);
17 if staleness_check.status == DoctorStatus::Warn && report.overall == DoctorStatus::Pass {
18 report.overall = DoctorStatus::Warn;
19 }
20 report.checks.push(staleness_check);
21 }
22
23 if json {
24 let output = serde_json::to_string_pretty(&report).map_err(|e| {
25 crate::error::ChronicleError::Json {
26 source: e,
27 location: snafu::Location::default(),
28 }
29 })?;
30 println!("{output}");
31 } else {
32 println!("chronicle doctor");
33 for check in &report.checks {
34 let icon = match check.status {
35 DoctorStatus::Pass => "pass",
36 DoctorStatus::Warn => "warn",
37 DoctorStatus::Fail => "FAIL",
38 };
39 println!(" [{icon}] {}: {}", check.name, check.message);
40 if let Some(ref hint) = check.fix_hint {
41 println!(" {hint}");
42 }
43 }
44 println!();
45 let overall = match report.overall {
46 DoctorStatus::Pass => "all checks passed",
47 DoctorStatus::Warn => "some warnings",
48 DoctorStatus::Fail => "some checks failed",
49 };
50 println!("Overall: {overall}");
51 }
52
53 if report.has_failures() {
54 std::process::exit(1);
55 }
56
57 Ok(())
58}
59
60fn check_staleness(git_ops: &dyn GitOps) -> DoctorCheck {
62 match crate::read::staleness::scan_staleness(git_ops, 50) {
63 Ok(report) => {
64 if report.stale_count == 0 {
65 DoctorCheck {
66 name: "staleness".to_string(),
67 status: DoctorStatus::Pass,
68 message: format!(
69 "{} annotations checked, none stale",
70 report.total_annotations
71 ),
72 fix_hint: None,
73 }
74 } else {
75 DoctorCheck {
76 name: "staleness".to_string(),
77 status: DoctorStatus::Warn,
78 message: format!(
79 "{} stale annotation(s) out of {} checked",
80 report.stale_count, report.total_annotations
81 ),
82 fix_hint: Some(
83 "Run `git chronicle annotate` on stale files to refresh annotations."
84 .to_string(),
85 ),
86 }
87 }
88 }
89 Err(_) => DoctorCheck {
90 name: "staleness".to_string(),
91 status: DoctorStatus::Warn,
92 message: "could not check staleness".to_string(),
93 fix_hint: None,
94 },
95 }
96}