Skip to main content

aster_cli/commands/
info.rs

1use anyhow::Result;
2use aster::config::paths::Paths;
3use aster::config::Config;
4use aster::session::session_manager::{DB_NAME, SESSIONS_FOLDER};
5use console::style;
6use serde_yaml;
7
8fn print_aligned(label: &str, value: &str, width: usize) {
9    println!("  {:<width$} {}", label, value, width = width);
10}
11
12use aster::config::base::CONFIG_YAML_NAME;
13use std::fs;
14use std::path::Path;
15
16fn check_path_status(path: &Path) -> String {
17    if path.exists() {
18        "".to_string()
19    } else {
20        let mut current = path.parent();
21        while let Some(parent) = current {
22            if parent.exists() {
23                return match fs::metadata(parent).map(|m| !m.permissions().readonly()) {
24                    Ok(true) => style("missing (can create)").dim().to_string(),
25                    Ok(false) => style("missing (read-only parent)").red().to_string(),
26                    Err(_) => style("missing (cannot check)").red().to_string(),
27                };
28            }
29            current = parent.parent();
30        }
31        style("missing (no writable parent)").red().to_string()
32    }
33}
34
35pub fn handle_info(verbose: bool) -> Result<()> {
36    let logs_dir = Paths::in_state_dir("logs");
37    let sessions_dir = Paths::in_data_dir(SESSIONS_FOLDER);
38    let sessions_db = sessions_dir.join(DB_NAME);
39    let config = Config::global();
40    let config_dir = Paths::config_dir();
41    let config_yaml_file = config_dir.join(CONFIG_YAML_NAME);
42
43    let paths = [
44        ("Config dir:", &config_dir),
45        ("Config yaml:", &config_yaml_file),
46        ("Sessions DB (sqlite):", &sessions_db),
47        ("Logs dir:", &logs_dir),
48    ];
49
50    let label_padding = paths.iter().map(|(l, _)| l.len()).max().unwrap_or(0) + 4;
51    let path_padding = paths
52        .iter()
53        .map(|(_, p)| p.display().to_string().len())
54        .max()
55        .unwrap_or(0)
56        + 4;
57
58    println!("{}", style("aster Version:").cyan().bold());
59    print_aligned("Version:", env!("CARGO_PKG_VERSION"), label_padding);
60    println!();
61
62    println!("{}", style("Paths:").cyan().bold());
63    for (label, path) in &paths {
64        println!(
65            "{:<label_padding$}{:<path_padding$}{}",
66            label,
67            path.display(),
68            check_path_status(path)
69        );
70    }
71
72    if verbose {
73        println!("\n{}", style("aster Configuration:").cyan().bold());
74        let values = config.all_values()?;
75        if values.is_empty() {
76            println!("  No configuration values set");
77            println!(
78                "  Run '{}' to configure aster",
79                style("aster configure").cyan()
80            );
81        } else {
82            let sorted_values: std::collections::BTreeMap<_, _> =
83                values.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
84
85            if let Ok(yaml) = serde_yaml::to_string(&sorted_values) {
86                for line in yaml.lines() {
87                    println!("  {}", line);
88                }
89            }
90        }
91    }
92
93    Ok(())
94}