chub_cli/commands/
check.rs1use clap::Args;
2use owo_colors::OwoColorize;
3
4use chub_core::team::freshness;
5
6use crate::output;
7
8#[derive(Args)]
9pub struct CheckArgs {
10 #[arg(long)]
12 fix: bool,
13}
14
15pub fn run(args: CheckArgs, json: bool) {
16 let cwd = std::env::current_dir().unwrap_or_default();
17 let results = freshness::check_freshness(&cwd);
18
19 if results.is_empty() {
20 if json {
21 println!(
22 "{}",
23 serde_json::json!({ "status": "no_pins", "results": [] })
24 );
25 } else {
26 eprintln!(
27 "{}",
28 "No pins to check. Use `chub pin add <id>` first.".dimmed()
29 );
30 }
31 return;
32 }
33
34 let outdated_count = results
35 .iter()
36 .filter(|r| r.status == freshness::FreshnessStatus::Outdated)
37 .count();
38
39 if json {
40 let items: Vec<serde_json::Value> = results
41 .iter()
42 .map(|r| {
43 serde_json::json!({
44 "id": r.pin_id,
45 "status": r.status,
46 "pinned_version": r.pinned_version,
47 "installed_version": r.installed_version,
48 "suggestion": r.suggestion,
49 })
50 })
51 .collect();
52 println!(
53 "{}",
54 serde_json::to_string_pretty(&serde_json::json!({
55 "results": items,
56 "outdated": outdated_count,
57 }))
58 .unwrap_or_default()
59 );
60 } else {
61 for r in &results {
62 match r.status {
63 freshness::FreshnessStatus::Current => {
64 eprintln!(" {} {} docs are current", "✓".green(), r.pin_id.bold());
65 }
66 freshness::FreshnessStatus::Outdated => {
67 eprintln!(
68 " {} {} pinned to {} docs, but {} is installed",
69 "⚠".yellow(),
70 r.pin_id.bold(),
71 r.pinned_version.as_deref().unwrap_or("?"),
72 r.installed_version.as_deref().unwrap_or("?"),
73 );
74 if let Some(ref suggestion) = r.suggestion {
75 eprintln!(" → {}", suggestion.dimmed());
76 }
77 }
78 freshness::FreshnessStatus::Unknown => {
79 eprintln!(
80 " {} {} (no matching dependency found)",
81 "?".dimmed(),
82 r.pin_id.bold(),
83 );
84 }
85 }
86 }
87
88 if outdated_count > 0 {
89 eprintln!(
90 "\n{} outdated pin(s) found. Run {} to update.",
91 outdated_count,
92 "chub check --fix".bold()
93 );
94 } else {
95 eprintln!("\n{}", "All pins are current.".green());
96 }
97 }
98
99 if args.fix && outdated_count > 0 {
100 let fixed = freshness::auto_fix_freshness(&results);
101 if json {
102 println!(
103 "{}",
104 serde_json::to_string_pretty(&serde_json::json!({
105 "fixed": fixed.len(),
106 "status": "updated",
107 }))
108 .unwrap_or_default()
109 );
110 } else {
111 output::success(&format!("Updated {} pin(s).", fixed.len()));
112 }
113 }
114}