use std::process::Command;
use serde_derive::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Clone)]
pub struct Env {
pub name: String,
pub version: String,
pub path: String,
pub is_cmd: bool,
}
#[derive(Deserialize, Serialize)]
pub struct EnvVec {
#[serde(skip_serializing_if = "Option::is_none")]
pub node: Option<Env>,
#[serde(skip_serializing_if = "Option::is_none")]
pub npm: Option<Env>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pnpm: Option<Env>,
#[serde(skip_serializing_if = "Option::is_none")]
pub yarn: Option<Env>,
}
impl Env {
pub fn new(name: &str) -> Option<Self> {
let mut env = Env {
name: String::from(""),
version: String::from(""),
path: String::from(""),
is_cmd: false,
};
match name {
"node" => env.is_cmd = false,
_ => env.is_cmd = true,
}
env.name = name.to_string();
let env = get_command_info(env);
if env.path.is_empty() {
None
} else {
Some(env)
}
}
}
pub fn get_command_info(mut command: Env) -> Env {
let which_cmd = if cfg!(windows) { "where" } else { "which" };
let path = Command::new(which_cmd)
.arg(&command.name)
.output()
.ok()
.and_then(|output| {
if output.status.success() {
Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
} else {
None
}
});
let command_sys_cmd = if cfg!(windows) && command.is_cmd {
format!("{}.cmd", &command.name)
} else {
command.name.clone()
};
command.path = path.unwrap_or_default();
let version = Command::new(command_sys_cmd)
.arg("-v")
.output()
.ok()
.and_then(|output| {
if output.status.success() {
Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
} else {
None
}
});
command.version = version.unwrap_or_default();
command
}