1use std::path::PathBuf;
2
3use crate::doctor::{run_doctor, DoctorStatus};
4use crate::error::Result;
5use crate::git::CliOps;
6
7pub fn run(json: 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 report = run_doctor(&git_ops, &git_dir)?;
14
15 if json {
16 let output = serde_json::to_string_pretty(&report).map_err(|e| {
17 crate::error::ChronicleError::Json {
18 source: e,
19 location: snafu::Location::default(),
20 }
21 })?;
22 println!("{output}");
23 } else {
24 println!("chronicle doctor");
25 for check in &report.checks {
26 let icon = match check.status {
27 DoctorStatus::Pass => "pass",
28 DoctorStatus::Warn => "warn",
29 DoctorStatus::Fail => "FAIL",
30 };
31 println!(" [{icon}] {}: {}", check.name, check.message);
32 if let Some(ref hint) = check.fix_hint {
33 println!(" {hint}");
34 }
35 }
36 println!();
37 let overall = match report.overall {
38 DoctorStatus::Pass => "all checks passed",
39 DoctorStatus::Warn => "some warnings",
40 DoctorStatus::Fail => "some checks failed",
41 };
42 println!("Overall: {overall}");
43 }
44
45 if report.has_failures() {
46 std::process::exit(1);
47 }
48
49 Ok(())
50}
51
52fn find_git_dir() -> Result<PathBuf> {
54 let output = std::process::Command::new("git")
55 .args(["rev-parse", "--git-dir"])
56 .output()
57 .map_err(|e| crate::error::ChronicleError::Io {
58 source: e,
59 location: snafu::Location::default(),
60 })?;
61
62 if output.status.success() {
63 let dir = String::from_utf8_lossy(&output.stdout).trim().to_string();
64 let path = PathBuf::from(&dir);
65 if path.is_relative() {
66 let cwd = std::env::current_dir().map_err(|e| crate::error::ChronicleError::Io {
67 source: e,
68 location: snafu::Location::default(),
69 })?;
70 Ok(cwd.join(path))
71 } else {
72 Ok(path)
73 }
74 } else {
75 let cwd = std::env::current_dir().map_err(|e| crate::error::ChronicleError::Io {
76 source: e,
77 location: snafu::Location::default(),
78 })?;
79 Err(crate::error::chronicle_error::NotARepositorySnafu { path: cwd }.build())
80 }
81}