use anyhow::{Context, Result};
use std::env;
use std::path::{Path, PathBuf};
use std::process;
mod config;
mod executor;
mod platform;
mod shim;
use config::ShimConfig;
use executor::Executor;
fn main() {
let result = run();
match result {
Ok(exit_code) => process::exit(exit_code),
Err(e) => {
eprintln!("vx-shim error: {}", e);
process::exit(1);
}
}
}
fn run() -> Result<i32> {
let current_exe = env::current_exe().context("Failed to get current executable path")?;
let shim_file = find_shim_file(¤t_exe)?;
let config = ShimConfig::load(&shim_file)
.with_context(|| format!("Failed to load shim config from {}", shim_file.display()))?;
let args: Vec<String> = env::args().skip(1).collect();
let executor = Executor::new(config);
executor
.execute(&args)
.context("Failed to execute target program")
}
fn find_shim_file(exe_path: &Path) -> Result<PathBuf> {
let mut shim_path = exe_path.to_path_buf();
if let Some(extension) = shim_path.extension() {
if extension == "exe" {
shim_path.set_extension("shim");
} else {
let mut new_extension = extension.to_os_string();
new_extension.push(".shim");
shim_path.set_extension(new_extension);
}
} else {
let mut new_name = shim_path
.file_name()
.context("Invalid executable path")?
.to_os_string();
new_name.push(".shim");
shim_path.set_file_name(new_name);
}
if !shim_path.exists() {
anyhow::bail!("Shim file not found: {}", shim_path.display());
}
Ok(shim_path)
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_find_shim_file() {
let temp_dir = TempDir::new().unwrap();
let temp_path = temp_dir.path();
let exe_path = temp_path.join("test.exe");
let shim_path = temp_path.join("test.shim");
fs::write(&shim_path, "path = /bin/echo\n").unwrap();
let result = find_shim_file(&exe_path).unwrap();
assert_eq!(result, shim_path);
}
#[test]
fn test_find_shim_file_no_extension() {
let temp_dir = TempDir::new().unwrap();
let temp_path = temp_dir.path();
let exe_path = temp_path.join("test");
let shim_path = temp_path.join("test.shim");
fs::write(&shim_path, "path = /bin/echo\n").unwrap();
let result = find_shim_file(&exe_path).unwrap();
assert_eq!(result, shim_path);
}
#[test]
fn test_find_shim_file_missing() {
let temp_dir = TempDir::new().unwrap();
let temp_path = temp_dir.path();
let exe_path = temp_path.join("test.exe");
let result = find_shim_file(&exe_path);
assert!(result.is_err());
}
}