use std::io;
use std::process::Command;
fn version_flag(name: &str) -> &'static str {
match name {
"ssh" => "-V",
"cosign" => "version",
_ => "--version",
}
}
pub fn tool_available(name: &str) -> io::Result<bool> {
Command::new(name)
.arg(version_flag(name))
.current_dir(crate::path_util::probe_dir())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.map(|s| s.success())
}
pub fn tool_version(name: &str) -> io::Result<Option<String>> {
let output = Command::new(name)
.arg(version_flag(name))
.current_dir(crate::path_util::probe_dir())
.output()?;
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
let line = stdout.lines().next().unwrap_or("").trim().to_string();
if !line.is_empty() {
return Ok(Some(line));
}
let stderr = String::from_utf8_lossy(&output.stderr);
Ok(Some(stderr.lines().next().unwrap_or("").trim().to_string()))
} else {
Ok(None)
}
}
pub fn tool_runs_with_args(name: &str, args: &[&str]) -> bool {
Command::new(name)
.args(args)
.current_dir(crate::path_util::probe_dir())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.map(|s| s.success())
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[cfg(unix)]
fn tool_runs_with_args_returns_true_for_existing_zero_exit_tool() {
assert!(tool_runs_with_args("true", &[]));
}
#[test]
fn tool_runs_with_args_returns_false_for_missing_binary() {
assert!(!tool_runs_with_args(
"nonexistent-binary-xyzzy",
&["--version"]
));
}
#[test]
fn version_flag_maps_ssh_to_dash_v() {
assert_eq!(version_flag("ssh"), "-V");
assert_eq!(version_flag("git"), "--version");
}
}