vx_cli/commands/
stats.rs

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