use super::{ToolState, remediation};
use crate::cli_outbound::{Binary, Chunk, Cli, ExitInfo, Stream};
use std::io;
const LERNIE_VERBS: [&str; 7] = [
"prime", "new", "prompt", "message", "stop", "scan", "config",
];
const BL_VERBS: [&str; 8] = [
"create", "claim", "unclaim", "close", "update", "list", "show", "conf",
];
const HELP: &str = "--help";
const VERSION: &str = "--version";
pub trait ToolProbe {
fn status(&self, binary: Binary, args: &[&str]) -> io::Result<i32>;
}
fn probes(binary: Binary) -> Vec<(&'static str, Vec<&'static str>)> {
match binary {
Binary::Lernie => LERNIE_VERBS.iter().map(|v| (*v, vec![*v, HELP])).collect(),
Binary::Bl => BL_VERBS.iter().map(|v| (*v, vec![*v, HELP])).collect(),
Binary::Bz => vec![(VERSION, vec![VERSION])],
}
}
pub(crate) fn classify(runner: &dyn ToolProbe, binary: Binary) -> ToolState {
for (verb, args) in probes(binary) {
match runner.status(binary, &args) {
Ok(0) => {}
Ok(_) => {
return ToolState::Mismatch {
verb: verb.to_owned(),
remediation: remediation(binary).to_owned(),
};
}
Err(_) => {
return ToolState::Missing {
remediation: remediation(binary).to_owned(),
};
}
}
}
ToolState::Ok
}
pub struct CliProbe {
bl: Cli,
lernie: Cli,
bz: Cli,
}
impl CliProbe {
pub fn new(bl: Cli, lernie: Cli, bz: Cli) -> Self {
Self { bl, lernie, bz }
}
fn cli(&self, binary: Binary) -> &Cli {
match binary {
Binary::Bl => &self.bl,
Binary::Lernie => &self.lernie,
Binary::Bz => &self.bz,
}
}
}
impl ToolProbe for CliProbe {
fn status(&self, binary: Binary, args: &[&str]) -> io::Result<i32> {
let stream = self.cli(binary).run(args).map_err(io::Error::other)?;
Ok(drain_exit(stream))
}
}
fn drain_exit(stream: Stream) -> i32 {
let mut exit = ExitInfo::Unknown;
for chunk in stream {
if let Chunk::Exited(e) = chunk {
exit = e;
}
}
exit.shell_code()
}