#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InstallMethod {
Source(std::path::PathBuf),
CargoInstall,
PrebuiltBinary,
}
impl InstallMethod {
pub fn detect() -> Self {
let exe = match std::env::current_exe() {
Ok(p) => p,
Err(_) => return Self::PrebuiltBinary,
};
if let Some(project_root) = find_cargo_project(&exe) {
return Self::Source(project_root);
}
if is_in_cargo_bin(&exe) {
return Self::CargoInstall;
}
Self::PrebuiltBinary
}
pub fn description(&self) -> &'static str {
match self {
Self::Source(_) => "source build",
Self::CargoInstall => "cargo install",
Self::PrebuiltBinary => "pre-built binary",
}
}
}
fn find_cargo_project(exe: &std::path::Path) -> Option<std::path::PathBuf> {
let mut dir = exe.parent()?.to_path_buf();
loop {
if dir.join("Cargo.toml").exists() {
return Some(dir);
}
if !dir.pop() {
return None;
}
}
}
fn is_in_cargo_bin(exe: &std::path::Path) -> bool {
let cargo_bin = cargo_bin_dir();
match cargo_bin {
Some(dir) => exe.parent().map(|p| p == dir).unwrap_or(false),
None => false,
}
}
fn cargo_bin_dir() -> Option<std::path::PathBuf> {
if let Ok(cargo_home) = std::env::var("CARGO_HOME") {
return Some(std::path::PathBuf::from(cargo_home).join("bin"));
}
dirs::home_dir().map(|h| h.join(".cargo").join("bin"))
}
pub fn platform_suffix() -> Option<&'static str> {
match (std::env::consts::OS, std::env::consts::ARCH) {
("macos", "aarch64") => Some("macos-arm64"),
("macos", "x86_64") => Some("macos-amd64"),
("linux", "x86_64") => Some("linux-amd64"),
("linux", "aarch64") => Some("linux-arm64"),
("windows", "x86_64") => Some("windows-amd64"),
_ => None,
}
}
pub fn binary_name() -> &'static str {
if std::env::consts::OS == "windows" {
"opencrabs.exe"
} else {
"opencrabs"
}
}