syncable_cli/analyzer/tool_management/installers/
common.rs

1use crate::error::Result;
2use log::{debug, info, warn};
3use std::process::Command;
4
5#[derive(Debug, Clone)]
6pub enum InstallationStrategy {
7    PackageManager(String), // e.g., "brew", "apt", "cargo"
8    DirectDownload { url: String, extract_to: String },
9    Script { command: String, args: Vec<String> },
10    Manual { instructions: String },
11}
12
13/// Common utilities for tool installation
14pub struct InstallationUtils;
15
16impl InstallationUtils {
17    /// Execute a command and return success status
18    pub fn execute_command(command: &str, args: &[&str]) -> Result<bool> {
19        debug!("Executing command: {} {}", command, args.join(" "));
20
21        let output = Command::new(command).args(args).output()?;
22
23        if output.status.success() {
24            info!(
25                "✅ Command executed successfully: {} {}",
26                command,
27                args.join(" ")
28            );
29            Ok(true)
30        } else {
31            let stderr = String::from_utf8_lossy(&output.stderr);
32            warn!(
33                "❌ Command failed: {} {} - {}",
34                command,
35                args.join(" "),
36                stderr
37            );
38            Ok(false)
39        }
40    }
41
42    /// Check if a command is available in PATH
43    pub fn is_command_available(command: &str) -> bool {
44        Command::new(command)
45            .arg("--version")
46            .output()
47            .map(|output| output.status.success())
48            .unwrap_or(false)
49    }
50
51    /// Get platform-specific installation directory
52    pub fn get_user_bin_dir() -> std::path::PathBuf {
53        if cfg!(windows) {
54            if let Ok(userprofile) = std::env::var("USERPROFILE") {
55                std::path::PathBuf::from(userprofile)
56                    .join(".local")
57                    .join("bin")
58            } else {
59                std::path::PathBuf::from(".").join("bin")
60            }
61        } else if let Ok(home) = std::env::var("HOME") {
62            std::path::PathBuf::from(home).join(".local").join("bin")
63        } else {
64            std::path::PathBuf::from(".").join("bin")
65        }
66    }
67
68    /// Create directory if it doesn't exist
69    pub fn ensure_dir_exists(path: &std::path::Path) -> Result<()> {
70        if !path.exists() {
71            std::fs::create_dir_all(path)?;
72            info!("Created directory: {}", path.display());
73        }
74        Ok(())
75    }
76}