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.rs106
1 files changed, 51 insertions, 55 deletions
diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs
index 793138588a..a77fed585a 100644
--- a/crates/toolchain/src/lib.rs
+++ b/crates/toolchain/src/lib.rs
@@ -16,18 +16,48 @@ pub enum Tool {
}
impl Tool {
+ pub fn proxy(self) -> Option<PathBuf> {
+ cargo_proxy(self.name())
+ }
+
+ /// Return a `PathBuf` to use for the given executable.
+ ///
+ /// The current implementation checks three places for an executable to use:
+ /// 1) `$CARGO_HOME/bin/<executable_name>`
+ /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
+ /// 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
+ /// 2) Appropriate environment variable (erroring if this is set but not a usable executable)
+ /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
+ /// 3) $PATH/`<executable_name>`
+ /// 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 {
+ invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name())
+ }
+
+ /// Return a `PathBuf` to use for the given executable.
+ ///
+ /// The current implementation checks three places for an executable to use:
+ /// 1) Appropriate environment variable (erroring if this is set but not a usable executable)
+ /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
+ /// 2) $PATH/`<executable_name>`
+ /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the
+ /// first that exists
+ /// 3) `$CARGO_HOME/bin/<executable_name>`
+ /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
+ /// 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 {
- get_path_for_executable(self.name())
+ invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name())
}
pub fn path_in(self, path: &Path) -> Option<PathBuf> {
probe_for_binary(path.join(self.name()))
}
- pub fn path_in_or_discover(self, path: &Path) -> PathBuf {
- probe_for_binary(path.join(self.name())).unwrap_or_else(|| self.path())
- }
-
pub fn name(self) -> &'static str {
match self {
Tool::Cargo => "cargo",
@@ -38,60 +68,21 @@ impl Tool {
}
}
-pub fn cargo() -> PathBuf {
- get_path_for_executable("cargo")
+fn invoke(list: &[fn(&str) -> Option<PathBuf>], executable: &str) -> PathBuf {
+ list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into())
}
-pub fn rustc() -> PathBuf {
- get_path_for_executable("rustc")
+/// 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)
}
-pub fn rustup() -> PathBuf {
- get_path_for_executable("rustup")
-}
-
-pub fn rustfmt() -> PathBuf {
- get_path_for_executable("rustfmt")
-}
-
-/// Return a `PathBuf` to use for the given executable.
-///
-/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
-/// gives a valid Cargo executable; or it may return a full path to a valid
-/// Cargo.
-fn get_path_for_executable(executable_name: &'static str) -> PathBuf {
- // The current implementation checks three places for an executable to use:
- // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
- // example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
- // 2) `$CARGO_HOME/bin/<executable_name>`
- // where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
- // 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
- // 3) `<executable_name>`
- // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
- let env_var = executable_name.to_ascii_uppercase();
- if let Some(path) = env::var_os(env_var) {
- return path.into();
- }
-
- if let Some(mut path) = get_cargo_home() {
- path.push("bin");
- path.push(executable_name);
- if let Some(path) = probe_for_binary(path) {
- return path;
- }
- }
-
- if lookup_in_path(executable_name) {
- return executable_name.into();
- }
-
- executable_name.into()
-}
-
-fn lookup_in_path(exec: &str) -> bool {
- let paths = env::var_os("PATH").unwrap_or_default();
- env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary).is_some()
+/// Looks up the binary in the cargo home directory if it exists.
+fn cargo_proxy(executable_name: &str) -> Option<PathBuf> {
+ let mut path = get_cargo_home()?;
+ path.push("bin");
+ path.push(executable_name);
+ probe_for_binary(path)
}
fn get_cargo_home() -> Option<PathBuf> {
@@ -107,6 +98,11 @@ fn get_cargo_home() -> Option<PathBuf> {
None
}
+fn lookup_in_path(exec: &str) -> Option<PathBuf> {
+ let paths = env::var_os("PATH").unwrap_or_default();
+ env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary)
+}
+
pub fn probe_for_binary(path: PathBuf) -> Option<PathBuf> {
let with_extension = match env::consts::EXE_EXTENSION {
"" => None,