@@ -16,8 +16,42 @@ pub enum Tool {
1616}
1717
1818impl Tool {
19+ pub fn proxy ( self ) -> Option < PathBuf > {
20+ cargo_proxy ( self . name ( ) )
21+ }
22+
23+ /// Return a `PathBuf` to use for the given executable.
24+ ///
25+ /// The current implementation checks three places for an executable to use:
26+ /// 1) `$CARGO_HOME/bin/<executable_name>`
27+ /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
28+ /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
29+ /// It seems that this is a reasonable place to try for cargo, rustc, and rustup
30+ /// 2) Appropriate environment variable (erroring if this is set but not a usable executable)
31+ /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
32+ /// 3) $PATH/`<executable_name>`
33+ /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the
34+ /// first that exists
35+ /// 4) If all else fails, we just try to use the executable name directly
36+ pub fn prefer_proxy ( self ) -> PathBuf {
37+ invoke ( & [ cargo_proxy, lookup_as_env_var, lookup_in_path] , self . name ( ) )
38+ }
39+
40+ /// Return a `PathBuf` to use for the given executable.
41+ ///
42+ /// The current implementation checks three places for an executable to use:
43+ /// 1) Appropriate environment variable (erroring if this is set but not a usable executable)
44+ /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
45+ /// 2) $PATH/`<executable_name>`
46+ /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the
47+ /// first that exists
48+ /// 3) `$CARGO_HOME/bin/<executable_name>`
49+ /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
50+ /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
51+ /// It seems that this is a reasonable place to try for cargo, rustc, and rustup
52+ /// 4) If all else fails, we just try to use the executable name directly
1953 pub fn path ( self ) -> PathBuf {
20- get_path_for_executable ( self . name ( ) )
54+ invoke ( & [ lookup_as_env_var , lookup_in_path , cargo_proxy ] , self . name ( ) )
2155 }
2256
2357 pub fn path_in ( self , path : & Path ) -> Option < PathBuf > {
@@ -38,60 +72,21 @@ impl Tool {
3872 }
3973}
4074
41- pub fn cargo ( ) -> PathBuf {
42- get_path_for_executable ( "cargo" )
43- }
44-
45- pub fn rustc ( ) -> PathBuf {
46- get_path_for_executable ( "rustc" )
75+ fn invoke ( list : & [ fn ( & str ) -> Option < PathBuf > ] , executable : & str ) -> PathBuf {
76+ list. iter ( ) . find_map ( |it| it ( executable) ) . unwrap_or_else ( || executable. into ( ) )
4777}
4878
49- pub fn rustup ( ) -> PathBuf {
50- get_path_for_executable ( "rustup" )
79+ /// Looks up the binary as its SCREAMING upper case in the env variables.
80+ fn lookup_as_env_var ( executable_name : & str ) -> Option < PathBuf > {
81+ env:: var_os ( executable_name. to_ascii_uppercase ( ) ) . map ( Into :: into)
5182}
5283
53- pub fn rustfmt ( ) -> PathBuf {
54- get_path_for_executable ( "rustfmt" )
55- }
56-
57- /// Return a `PathBuf` to use for the given executable.
58- ///
59- /// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
60- /// gives a valid Cargo executable; or it may return a full path to a valid
61- /// Cargo.
62- fn get_path_for_executable ( executable_name : & ' static str ) -> PathBuf {
63- // The current implementation checks three places for an executable to use:
64- // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
65- // example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
66- // 2) `<executable_name>`
67- // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
68- // 3) `$CARGO_HOME/bin/<executable_name>`
69- // where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
70- // example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
71- // It seems that this is a reasonable place to try for cargo, rustc, and rustup
72- let env_var = executable_name. to_ascii_uppercase ( ) ;
73- if let Some ( path) = env:: var_os ( env_var) {
74- return path. into ( ) ;
75- }
76-
77- if lookup_in_path ( executable_name) {
78- return executable_name. into ( ) ;
79- }
80-
81- if let Some ( mut path) = get_cargo_home ( ) {
82- path. push ( "bin" ) ;
83- path. push ( executable_name) ;
84- if let Some ( path) = probe_for_binary ( path) {
85- return path;
86- }
87- }
88-
89- executable_name. into ( )
90- }
91-
92- fn lookup_in_path ( exec : & str ) -> bool {
93- let paths = env:: var_os ( "PATH" ) . unwrap_or_default ( ) ;
94- env:: split_paths ( & paths) . map ( |path| path. join ( exec) ) . find_map ( probe_for_binary) . is_some ( )
84+ /// Looks up the binary in the cargo home directory if it exists.
85+ fn cargo_proxy ( executable_name : & str ) -> Option < PathBuf > {
86+ let mut path = get_cargo_home ( ) ?;
87+ path. push ( "bin" ) ;
88+ path. push ( executable_name) ;
89+ probe_for_binary ( path)
9590}
9691
9792fn get_cargo_home ( ) -> Option < PathBuf > {
@@ -107,6 +102,11 @@ fn get_cargo_home() -> Option<PathBuf> {
107102 None
108103}
109104
105+ fn lookup_in_path ( exec : & str ) -> Option < PathBuf > {
106+ let paths = env:: var_os ( "PATH" ) . unwrap_or_default ( ) ;
107+ env:: split_paths ( & paths) . map ( |path| path. join ( exec) ) . find_map ( probe_for_binary)
108+ }
109+
110110pub fn probe_for_binary ( path : PathBuf ) -> Option < PathBuf > {
111111 let with_extension = match env:: consts:: EXE_EXTENSION {
112112 "" => None ,
0 commit comments