vx_cli/commands/
stats.rs

1// Stats and cleanup command implementation
2
3use crate::ui::UI;
4use anyhow::Result;
5use vx_plugin::PluginRegistry;
6
7pub async fn handle(registry: &PluginRegistry) -> Result<()> {
8    show_all_stats(registry).await
9}
10
11pub async fn handle_cleanup(cache: bool, orphaned: bool, dry_run: bool) -> Result<()> {
12    if dry_run {
13        UI::header("Cleanup Preview (Dry Run)");
14    } else {
15        UI::header("Cleaning up...");
16    }
17
18    // TODO: Replace with vx-core executor
19    // let mut executor = crate::executor::Executor::new()?;
20
21    if cache || !orphaned {
22        if dry_run {
23            UI::info("Would clean cache directories");
24        } else {
25            UI::step("Cleaning cache...");
26            UI::warning("Cache cleanup not yet implemented in new architecture");
27            // TODO: Implement cache cleanup
28        }
29    }
30
31    if orphaned || !cache {
32        if dry_run {
33            UI::info("Would clean orphaned packages");
34        } else {
35            UI::step("Cleaning orphaned packages...");
36            UI::warning("Orphaned package cleanup not yet implemented in new architecture");
37            // executor.cleanup()?;
38        }
39    }
40
41    if !dry_run {
42        UI::success("Cleanup completed");
43    }
44
45    Ok(())
46}
47
48#[allow(dead_code)]
49async fn show_tool_stats(tool_name: &str, _detailed: bool) -> Result<()> {
50    UI::header(&format!("Statistics for {tool_name}"));
51    UI::warning("Tool stats not yet implemented in new architecture");
52
53    // TODO: Replace with vx-core package manager
54    // let package_manager = crate::package_manager::PackageManager::new()?;
55    // let versions = package_manager.list_versions(tool_name);
56
57    // if versions.is_empty() {
58    //     UI::warning(&format!("Tool '{tool_name}' is not installed"));
59    //     return Ok(());
60    // }
61
62    // let mut total_size = 0u64;
63    // let version_count = versions.len();
64
65    // if detailed {
66    //     println!("Installed versions:");
67    //     for version in &versions {
68    //         if let Ok(path) = package_manager.get_version_path(tool_name, version) {
69    //             let size = calculate_directory_size(&path).unwrap_or(0);
70    //             total_size += size;
71    //             println!("  {} - {} ({})", version, format_size(size), path.display());
72    //         }
73    //     }
74    //     println!();
75    // } else {
76    //     for version in &versions {
77    //         if let Ok(path) = package_manager.get_version_path(tool_name, version) {
78    //             total_size += calculate_directory_size(&path).unwrap_or(0);
79    //         }
80    //     }
81    // }
82
83    // println!("Total versions: {version_count}");
84    // println!("Total size: {}", format_size(total_size));
85
86    Ok(())
87}
88
89async fn show_all_stats(_registry: &PluginRegistry) -> Result<()> {
90    let spinner = UI::new_spinner("Collecting package statistics...");
91    UI::warning("Package statistics not yet implemented in new architecture");
92
93    // TODO: Replace with vx-core executor
94    // let mut executor = crate::executor::Executor::new()?;
95    // let stats = executor.get_stats()?;
96    spinner.finish_and_clear();
97
98    // UI::show_stats(
99    //     stats.total_packages,
100    //     stats.total_versions,
101    //     stats.total_size,
102    //     &stats
103    //         .last_updated
104    //         .format("%Y-%m-%d %H:%M:%S UTC")
105    //         .to_string(),
106    // );
107
108    // List installed packages
109    // if let Ok(packages) = executor.list_installed_packages() {
110    //     if !packages.is_empty() {
111    //         if detailed {
112    //             println!();
113    //             UI::header("Installed Packages");
114    //             for package in &packages {
115    //                 println!(
116    //                     "  {} {} - {}",
117    //                     package.name, package.version, &package.metadata.description
118    //                 );
119    //             }
120    //         } else {
121    //             // Create a simple list without active status for now
122    //             let package_list: Vec<(String, String, bool)> = packages
123    //                 .iter()
124    //                 .map(|package| {
125    //                     // For now, mark all as inactive to avoid borrowing issues
126    //                     // TODO: Improve this to show actual active status
127    //                     (package.name.clone(), package.version.clone(), false)
128    //                 })
129    //                 .collect();
130
131    //             println!();
132    //             UI::show_package_list(&package_list);
133    //         }
134    //     }
135    // }
136
137    Ok(())
138}
139
140#[allow(dead_code)]
141fn calculate_directory_size(path: &std::path::Path) -> Result<u64> {
142    if path.is_file() {
143        Ok(path.metadata()?.len())
144    } else if path.is_dir() {
145        let mut size = 0;
146        for entry in walkdir::WalkDir::new(path) {
147            let entry = entry?;
148            if entry.file_type().is_file() {
149                size += entry.metadata()?.len();
150            }
151        }
152        Ok(size)
153    } else {
154        Ok(0)
155    }
156}
157
158#[allow(dead_code)]
159fn format_size(bytes: u64) -> String {
160    const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
161    let mut size = bytes as f64;
162    let mut unit_index = 0;
163
164    while size >= 1024.0 && unit_index < UNITS.len() - 1 {
165        size /= 1024.0;
166        unit_index += 1;
167    }
168
169    if unit_index == 0 {
170        format!("{} {}", bytes, UNITS[unit_index])
171    } else {
172        format!("{:.1} {}", size, UNITS[unit_index])
173    }
174}