use std::error::Error;
use std::process::Command;
use log::{info, warn, error};
use semver::Version;
use std::path::Path;
pub fn check_system_requirements() -> Result<(), String> {
info!("Checking system requirements...");
check_rust_version()?;
check_docker_version()?;
check_disk_space()?;
check_memory()?;
info!("System requirements checked successfully");
Ok(())
}
pub fn verify_installation() -> Result<(), String> {
info!("Verifying installation...");
verify_core_components()?;
if Path::new("config/bitcoin").exists() {
verify_bitcoin_components()?;
}
if Path::new("config/dao").exists() {
verify_dao_components()?;
}
if Path::new("config/web5").exists() {
verify_web5_components()?;
}
if Path::new("config/ml").exists() {
verify_ml_components()?;
}
info!("Installation verified successfully");
Ok(())
}
fn check_rust_version() -> Result<(), String> {
let output = Command::new("rustc")
.arg("--version")
.output();
match output {
Ok(output) => {
if !output.status.success() {
return Err("Failed to execute rustc".to_string());
}
let version_str = String::from_utf8_lossy(&output.stdout);
let version_parts: Vec<&str> = version_str.split(' ').collect();
if version_parts.len() < 2 {
return Err(format!("Invalid rustc version format: {}", version_str));
}
let version = match Version::parse(version_parts[1]) {
Ok(v) => v,
Err(e) => return Err(format!("Failed to parse rustc version: {}", e)),
};
let min_version = Version::parse("1.70.0")?;
if version < min_version {
return Err(format!("Rust version {} is too old, minimum required is 1.70.0", version));
}
info!("Rust version {} detected", version);
Ok(())
},
Err(e) => Err(format!("Failed to check Rust version: {}", e)),
}
}
fn check_docker_version() -> Result<(), String> {
let output = Command::new("docker")
.arg("--version")
.output();
match output {
Ok(output) => {
if !output.status.success() {
return Err("Failed to execute docker".to_string());
}
let version_str = String::from_utf8_lossy(&output.stdout);
info!("Docker version detected: {}", version_str.trim());
Ok(())
},
Err(e) => Err(format!("Failed to check Docker version: {}", e)),
}
}
fn check_disk_space() -> Result<(), String> {
info!("Checking disk space requirements...");
#[cfg(unix)]
{
let output = Command::new("df")
.args(&["-h", "."])
.output();
match output {
Ok(output) => {
if !output.status.success() {
return Err("Failed to execute df command".to_string());
}
let output_str = String::from_utf8_lossy(&output.stdout);
info!("Disk space check: {}", output_str.trim());
Ok(())
},
Err(e) => Err(format!("Failed to check disk space: {}", e)),
}
}
#[cfg(windows)]
{
info!("Disk space check: Windows implementation");
Ok(())
}
}
fn check_memory() -> Result<(), String> {
info!("Checking memory requirements...");
#[cfg(unix)]
{
let output = Command::new("free")
.args(&["-h"])
.output();
match output {
Ok(output) => {
if !output.status.success() {
return Err("Failed to execute free command".to_string());
}
let output_str = String::from_utf8_lossy(&output.stdout);
info!("Memory check: {}", output_str.trim());
Ok(())
},
Err(e) => Err(format!("Failed to check memory: {}", e)),
}
}
#[cfg(windows)]
{
info!("Memory check: Windows implementation");
Ok(())
}
}
fn verify_core_components() -> Result<(), String> {
info!("Verifying core components...");
for binary in &["anya-core", "anya-cli"] {
let binary_path = format!("bin/{}", binary);
if !Path::new(&binary_path).exists() {
return Err(format!("Core binary not found: {}", binary_path));
}
}
if !Path::new("config/core.toml").exists() {
return Err("Core configuration file not found".to_string());
}
Ok(())
}
fn verify_bitcoin_components() -> Result<(), String> {
info!("Verifying Bitcoin components...");
let output = Command::new("bitcoin-cli")
.arg("--version")
.output();
match output {
Ok(output) => {
if !output.status.success() {
return Err("Bitcoin Core is not properly installed".to_string());
}
let version_str = String::from_utf8_lossy(&output.stdout);
info!("Bitcoin Core version: {}", version_str.trim());
Ok(())
},
Err(e) => Err(format!("Failed to verify Bitcoin Core: {}", e)),
}
}
fn verify_dao_components() -> Result<(), String> {
info!("Verifying DAO components...");
if !Path::new("config/dao/contracts").exists() {
return Err("DAO contracts directory not found".to_string());
}
let output = Command::new("clarinet")
.arg("--version")
.output();
match output {
Ok(output) => {
if !output.status.success() {
return Err("Clarinet is not properly installed".to_string());
}
let version_str = String::from_utf8_lossy(&output.stdout);
info!("Clarinet version: {}", version_str.trim());
Ok(())
},
Err(e) => Err(format!("Failed to verify Clarinet: {}", e)),
}
}
fn verify_web5_components() -> Result<(), String> {
info!("Verifying Web5 components...");
if !Path::new("config/web5/dwn").exists() {
return Err("Web5 DWN directory not found".to_string());
}
Ok(())
}
fn verify_ml_components() -> Result<(), String> {
info!("Verifying ML components...");
if !Path::new("config/ml/models").exists() {
return Err("ML models directory not found".to_string());
}
Ok(())
}