use std::error::Error;
use std::fmt;
use std::path::Path;
use anyhow::{Context, Result, bail};
use xshell::Shell;
#[derive(Debug)]
pub struct ExitCode(i32);
impl ExitCode {
pub fn new(code: i32) -> Self {
Self(code)
}
pub fn code(&self) -> i32 {
self.0
}
}
impl fmt::Display for ExitCode {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "exit with status {}", self.0)
}
}
impl Error for ExitCode {}
pub fn shell() -> Result<Shell> {
Shell::new().context("create shell")
}
pub fn command_exists(program: &str) -> bool {
std::env::var_os("PATH").is_some_and(|path| {
std::env::split_paths(&path).any(|dir| {
let candidate = dir.join(program);
candidate.is_file()
})
})
}
pub fn ensure_command(program: &str) -> Result<()> {
if command_exists(program) {
Ok(())
} else {
bail!("{program} not found on PATH")
}
}
pub fn push_dir<'a>(sh: &'a Shell, path: impl AsRef<Path>) -> xshell::PushDir<'a> {
sh.push_dir(path)
}