Skip to main content

chub_cli/commands/
check.rs

1use clap::Args;
2use owo_colors::OwoColorize;
3
4use chub_core::team::freshness;
5
6use crate::output;
7
8#[derive(Args)]
9pub struct CheckArgs {
10    /// Auto-update outdated pins to current installed version
11    #[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}