#![forbid(unsafe_code)]
use std::path::{Path, PathBuf};
use std::process::{Command, ExitCode};
use vanta_core::{Platform, StoreKey};
use vanta_lock::Lock;
use vanta_state::State;
enum LockResolution {
Bin(PathBuf),
PinnedButMissing(String),
NotManaged,
}
fn basename(p: &str) -> &str {
p.rsplit(['/', '\\']).next().unwrap_or(p)
}
fn resolve_from_lock(home: &Path, name: &str) -> LockResolution {
let plat = Platform::current().token();
let mut dir = std::env::current_dir().ok();
while let Some(d) = dir {
let lock_path = d.join("vanta.lock");
if lock_path.is_file() {
if let Ok(lock) = Lock::load_file(&lock_path) {
for tool in &lock.tools {
let pin = tool.platform.get(&plat);
let manages = tool.name == name
|| pin.is_some_and(|p| p.bin.iter().any(|b| basename(b) == name));
if !manages {
continue;
}
let Some(pin) = pin.filter(|p| !p.store_key.is_empty()) else {
return LockResolution::PinnedButMissing(tool.version.clone());
};
let Ok(key) = StoreKey::new(pin.store_key.clone()) else {
return LockResolution::PinnedButMissing(tool.version.clone());
};
let rel = pin
.bin
.iter()
.find(|b| basename(b) == name)
.cloned()
.unwrap_or_else(|| name.to_string());
if Path::new(&rel).components().any(|c| {
matches!(
c,
std::path::Component::ParentDir
| std::path::Component::RootDir
| std::path::Component::Prefix(_)
)
}) {
return LockResolution::NotManaged;
}
let path = home.join("store").join(key.as_str()).join(&rel);
if path.is_file() {
return LockResolution::Bin(path);
}
return LockResolution::PinnedButMissing(tool.version.clone());
}
}
}
dir = d.parent().map(Path::to_path_buf);
}
LockResolution::NotManaged
}
#[must_use]
pub fn run() -> ExitCode {
let invoked = std::env::args()
.next()
.and_then(|p| {
Path::new(&p)
.file_name()
.map(|s| s.to_string_lossy().into_owned())
})
.unwrap_or_default();
let name = invoked.strip_suffix(".exe").unwrap_or(&invoked).to_string();
let args: Vec<String> = std::env::args().skip(1).collect();
match dispatch(&name, &args) {
Ok(code) => code,
Err(msg) => {
eprintln!("vanta-shim: {msg}");
ExitCode::from(1)
}
}
}
pub fn dispatch(name: &str, args: &[String]) -> Result<ExitCode, String> {
let home = home().ok_or("cannot determine VANTA_HOME")?;
match resolve_from_lock(&home, name) {
LockResolution::Bin(bin) => return exec(&bin, args),
LockResolution::PinnedButMissing(version) => {
return Err(format!(
"`{name}` is pinned to {version} here but not installed — run `vanta sync`"
));
}
LockResolution::NotManaged => {} }
let state = State::open(&home.join("state.db")).map_err(|e| e.to_string())?;
let id = state
.current()
.map_err(|e| e.to_string())?
.ok_or("no active generation")?;
let generation = state
.get_generation(id)
.map_err(|e| e.to_string())?
.ok_or("active generation is missing")?;
let (_, key) = generation
.tools
.iter()
.find(|(tool, _)| tool == name)
.ok_or_else(|| format!("`{name}` is not managed by vanta"))?;
let key = StoreKey::new(key.clone()).map_err(|e| e.to_string())?;
let entry = home.join("store").join(key.as_str());
let bin = find_bin(&entry, name)
.ok_or_else(|| format!("executable for `{name}` not found in {}", entry.display()))?;
exec(&bin, args)
}
fn find_bin(entry: &Path, name: &str) -> Option<PathBuf> {
let candidates = [
entry.join("bin").join(name),
entry.join(name),
entry.join("bin").join(format!("{name}.exe")),
entry.join(format!("{name}.exe")),
];
candidates.into_iter().find(|c| c.is_file())
}
#[cfg(unix)]
fn exec(bin: &Path, args: &[String]) -> Result<ExitCode, String> {
use std::os::unix::process::CommandExt;
let err = Command::new(bin).args(args).exec();
Err(format!("exec {}: {err}", bin.display()))
}
#[cfg(not(unix))]
fn exec(bin: &Path, args: &[String]) -> Result<ExitCode, String> {
let status = Command::new(bin)
.args(args)
.status()
.map_err(|e| format!("running {}: {e}", bin.display()))?;
Ok(ExitCode::from(status.code().unwrap_or(1) as u8))
}
fn home() -> Option<PathBuf> {
if let Ok(h) = std::env::var("VANTA_HOME") {
return Some(PathBuf::from(h));
}
std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE"))
.ok()
.map(|base| PathBuf::from(base).join(".vanta"))
}