vx_cli/commands/
install.rs

1//! Install command implementation
2
3use crate::ui::UI;
4use anyhow::Result;
5use tracing::{info_span, Instrument};
6use vx_plugin::PluginRegistry;
7
8pub async fn handle(
9    registry: &PluginRegistry,
10    tool_name: &str,
11    version: Option<&str>,
12    force: bool,
13) -> Result<()> {
14    // Get the tool from registry
15    let tool = registry
16        .get_tool(tool_name)
17        .ok_or_else(|| anyhow::anyhow!("Tool not found: {}", tool_name))?;
18
19    // Determine version to install
20    let target_version = if let Some(v) = version {
21        v.to_string()
22    } else {
23        // Get latest version with progress span
24        let span = info_span!("Fetching latest version", tool = tool_name);
25        let versions = async {
26            UI::info(&format!("Fetching latest version for {}...", tool_name));
27            tool.fetch_versions(false).await
28        }
29        .instrument(span)
30        .await?;
31
32        if versions.is_empty() {
33            return Err(anyhow::anyhow!("No versions found for tool: {}", tool_name));
34        }
35        versions[0].version.clone()
36    };
37
38    UI::info(&format!("Installing {} {}...", tool_name, target_version));
39
40    // Check if already installed
41    if !force && tool.is_version_installed(&target_version).await? {
42        UI::success(&format!(
43            "{} {} is already installed",
44            tool_name, target_version
45        ));
46        UI::hint("Use --force to reinstall");
47        return Ok(());
48    }
49
50    // Install the version with progress span
51    let install_span = info_span!("Installing tool", tool = tool_name, version = %target_version);
52    let install_result = async { tool.install_version(&target_version, force).await }
53        .instrument(install_span)
54        .await;
55
56    match install_result {
57        Ok(()) => {
58            UI::success(&format!(
59                "Successfully installed {} {}",
60                tool_name, target_version
61            ));
62
63            // Show installation path
64            let install_dir = tool.get_version_install_dir(&target_version);
65            UI::detail(&format!("Installed to: {}", install_dir.display()));
66
67            // Show usage hint
68            UI::hint(&format!(
69                "Use 'vx {} --version' to verify installation",
70                tool_name
71            ));
72        }
73        Err(e) => {
74            UI::error(&format!(
75                "Failed to install {} {}: {}",
76                tool_name, target_version, e
77            ));
78            return Err(e);
79        }
80    }
81
82    Ok(())
83}