use std::path::PathBuf;
use std::process::Output;
use tokio::process::Command;
use tracing::{debug, info};
use colored::Colorize;
pub async fn install_package(package_name: &str, debug: bool) -> Result<(), String> {
if package_name.is_empty() || package_name == "--help" || package_name == "help" {
list_available_packages();
return Ok(());
}
match package_name.to_lowercase().as_str() {
"grafana" => execute_install_script("grafana", debug).await,
"scylladb" => execute_install_script("scylladb", debug).await,
"nginx_full" => execute_install_script("nginx_full", debug).await,
"opencv-rust" => execute_install_script("opencv-rust", debug).await,
"elixir_erlang" => execute_install_script("elixir_erlang", debug).await,
"docker" => execute_install_script("docker", debug).await,
"triggerdotdev" => execute_install_script("triggerdotdev", debug).await,
"iotop" => execute_install_script("iotop", debug).await,
_ => {
info!("{} '{}'", "Unknown package:".red(), package_name);
info!("");
list_available_packages();
Err(format!("Package '{}' is not supported", package_name))
}
}
}
fn list_available_packages() {
info!("{}", "Available packages:".bright_blue().bold());
info!("");
info!(" {} - Monitoring and observability platform", "grafana".cyan());
info!(" {} - High-performance NoSQL database", "scylladb".cyan());
info!(" {} - Full Nginx installation with modules", "nginx_full".cyan());
info!(" {} - OpenCV bindings for Rust", "opencv-rust".cyan());
info!(" {} - Container platform", "docker".cyan());
info!(" {} - Elixir and Erlang runtime", "elixir_erlang".cyan());
info!(" {} - Background job framework", "triggerdotdev".cyan());
info!(" {} - I/O monitoring tool", "iotop".cyan());
info!("");
info!("{} {}", "Usage:".bright_blue(), "xbp install <package>".yellow());
}
async fn execute_install_script(package_name: &str, debug: bool) -> Result<(), String> {
let script_path: String = format!("./package_install_scripts/{}.sh", package_name);
let script_pathbuf: PathBuf = PathBuf::from(&script_path);
if debug {
debug!("Looking for install script at: {}", script_path);
}
if !script_pathbuf.exists() {
return Err(format!("Install script not found: {}", script_path));
}
if debug {
debug!("Making script executable: {}", script_path);
}
let chmod_output: Output = Command::new("chmod")
.arg("+x")
.arg(&script_path)
.output()
.await
.map_err(|e| format!("Failed to execute chmod command: {}", e))?;
if !chmod_output.status.success() {
return Err(format!(
"Failed to make script executable: {}",
String::from_utf8_lossy(&chmod_output.stderr)
));
}
if debug {
debug!("Executing install script: {}", script_path);
}
let script_output: Output = Command::new("bash")
.arg(&script_path)
.output()
.await
.map_err(|e| format!("Failed to execute install script: {}", e))?;
if debug {
debug!("Script output: {:?}", script_output);
}
if !script_output.status.success() {
return Err(format!(
"Install script failed: {}",
String::from_utf8_lossy(&script_output.stderr)
));
}
let stdout = String::from_utf8_lossy(&script_output.stdout);
if !stdout.trim().is_empty() {
info!("{}", stdout);
}
info!("{} installation completed successfully!", package_name);
Ok(())
}