Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/toolchain/src/lib.rs')
| -rw-r--r-- | crates/toolchain/src/lib.rs | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs index a77fed585a..b577723612 100644 --- a/crates/toolchain/src/lib.rs +++ b/crates/toolchain/src/lib.rs @@ -2,10 +2,9 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -use std::{ - env, iter, - path::{Path, PathBuf}, -}; +use std::{env, iter, path::PathBuf}; + +use camino::{Utf8Path, Utf8PathBuf}; #[derive(Copy, Clone)] pub enum Tool { @@ -16,7 +15,7 @@ pub enum Tool { } impl Tool { - pub fn proxy(self) -> Option<PathBuf> { + pub fn proxy(self) -> Option<Utf8PathBuf> { cargo_proxy(self.name()) } @@ -33,7 +32,7 @@ impl Tool { /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the /// first that exists /// 4) If all else fails, we just try to use the executable name directly - pub fn prefer_proxy(self) -> PathBuf { + pub fn prefer_proxy(self) -> Utf8PathBuf { invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name()) } @@ -50,11 +49,11 @@ impl Tool { /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. /// It seems that this is a reasonable place to try for cargo, rustc, and rustup /// 4) If all else fails, we just try to use the executable name directly - pub fn path(self) -> PathBuf { + pub fn path(self) -> Utf8PathBuf { invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name()) } - pub fn path_in(self, path: &Path) -> Option<PathBuf> { + pub fn path_in(self, path: &Utf8Path) -> Option<Utf8PathBuf> { probe_for_binary(path.join(self.name())) } @@ -68,42 +67,50 @@ impl Tool { } } -fn invoke(list: &[fn(&str) -> Option<PathBuf>], executable: &str) -> PathBuf { +fn invoke(list: &[fn(&str) -> Option<Utf8PathBuf>], executable: &str) -> Utf8PathBuf { list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into()) } /// Looks up the binary as its SCREAMING upper case in the env variables. -fn lookup_as_env_var(executable_name: &str) -> Option<PathBuf> { - env::var_os(executable_name.to_ascii_uppercase()).map(Into::into) +fn lookup_as_env_var(executable_name: &str) -> Option<Utf8PathBuf> { + env::var_os(executable_name.to_ascii_uppercase()) + .map(PathBuf::from) + .map(Utf8PathBuf::try_from) + .and_then(Result::ok) } /// Looks up the binary in the cargo home directory if it exists. -fn cargo_proxy(executable_name: &str) -> Option<PathBuf> { +fn cargo_proxy(executable_name: &str) -> Option<Utf8PathBuf> { let mut path = get_cargo_home()?; path.push("bin"); path.push(executable_name); probe_for_binary(path) } -fn get_cargo_home() -> Option<PathBuf> { +fn get_cargo_home() -> Option<Utf8PathBuf> { if let Some(path) = env::var_os("CARGO_HOME") { - return Some(path.into()); + return Utf8PathBuf::try_from(PathBuf::from(path)).ok(); } if let Some(mut path) = home::home_dir() { path.push(".cargo"); - return Some(path); + return Utf8PathBuf::try_from(path).ok(); } None } -fn lookup_in_path(exec: &str) -> Option<PathBuf> { +fn lookup_in_path(exec: &str) -> Option<Utf8PathBuf> { let paths = env::var_os("PATH").unwrap_or_default(); - env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary) + env::split_paths(&paths) + .map(|path| path.join(exec)) + .map(PathBuf::from) + .map(Utf8PathBuf::try_from) + .filter_map(Result::ok) + .find_map(probe_for_binary) } -pub fn probe_for_binary(path: PathBuf) -> Option<PathBuf> { +pub fn probe_for_binary(path: Utf8PathBuf) -> Option<Utf8PathBuf> { let with_extension = match env::consts::EXE_EXTENSION { "" => None, it => Some(path.with_extension(it)), |