11use std:: borrow:: Cow ;
2- use std:: env:: VarError ;
32use std:: ffi:: OsStr ;
43use std:: ffi:: OsString ;
54use std:: io;
@@ -63,14 +62,10 @@ pub trait Sys: Clone {
6362 fn home_dir ( & self ) -> Option < PathBuf > ;
6463 /// Splits a platform-specific PATH variable into a list of paths.
6564 fn env_split_paths ( & self , paths : & OsStr ) -> Vec < PathBuf > ;
66- /// Gets the value of an environment variable.
67- fn env_var_os ( & self , name : & OsStr ) -> Option < OsString > ;
68- fn env_var ( & self , key : & OsStr ) -> Result < String , VarError > {
69- match self . env_var_os ( key) {
70- Some ( val) => val. into_string ( ) . map_err ( VarError :: NotUnicode ) ,
71- None => Err ( VarError :: NotPresent ) ,
72- }
73- }
65+ /// Gets the value of the PATH environment variable.
66+ fn env_path ( & self ) -> Option < OsString > ;
67+ /// Gets the value of the PATHEXT environment variable. If not on Windows, simply return None.
68+ fn env_path_ext ( & self ) -> Option < OsString > ;
7469 /// Gets and parses the PATHEXT environment variable on Windows.
7570 ///
7671 /// Override this to enable caching the parsed PATHEXT.
@@ -80,7 +75,19 @@ pub trait Sys: Clone {
8075 /// can work in Wasm.
8176 fn env_windows_path_ext ( & self ) -> Cow < ' static , [ String ] > {
8277 Cow :: Owned (
83- self . env_var ( OsStr :: new ( "PATHEXT" ) )
78+ self . env_path_ext ( )
79+ . and_then ( |pathext| {
80+ // If tracing feature enabled then this lint is incorrect, so disable it.
81+ #[ allow( clippy:: manual_ok_err) ]
82+ match pathext. into_string ( ) {
83+ Ok ( pathext) => Some ( pathext) ,
84+ Err ( _) => {
85+ #[ cfg( feature = "tracing" ) ]
86+ tracing:: error!( "pathext is not valid unicode" ) ;
87+ None
88+ }
89+ }
90+ } )
8491 . map ( |pathext| parse_path_ext ( & pathext) )
8592 // PATHEXT not being set or not being a proper Unicode string is exceedingly
8693 // improbable and would probably break Windows badly. Still, don't crash:
@@ -180,7 +187,15 @@ impl Sys for RealSys {
180187 // hence its retention.)
181188 static PATH_EXTENSIONS : OnceLock < Vec < String > > = OnceLock :: new ( ) ;
182189 let path_extensions = PATH_EXTENSIONS . get_or_init ( || {
183- self . env_var ( OsStr :: new ( "PATHEXT" ) )
190+ self . env_path_ext ( )
191+ . and_then ( |pathext| match pathext. into_string ( ) {
192+ Ok ( pathext) => Some ( pathext) ,
193+ Err ( _) => {
194+ #[ cfg( feature = "tracing" ) ]
195+ tracing:: error!( "pathext is not valid unicode" ) ;
196+ None
197+ }
198+ } )
184199 . map ( |s| parse_path_ext ( & s) )
185200 // PATHEXT not being set or not being a proper Unicode string is exceedingly
186201 // improbable and would probably break Windows badly. Still, don't crash:
@@ -190,9 +205,15 @@ impl Sys for RealSys {
190205 }
191206
192207 #[ inline]
193- fn env_var_os ( & self , name : & OsStr ) -> Option < OsString > {
208+ fn env_path ( & self ) -> Option < OsString > {
209+ #[ allow( clippy:: disallowed_methods) ] // ok, sys implementation
210+ std:: env:: var_os ( "PATH" )
211+ }
212+
213+ #[ inline]
214+ fn env_path_ext ( & self ) -> Option < OsString > {
194215 #[ allow( clippy:: disallowed_methods) ] // ok, sys implementation
195- std:: env:: var_os ( name )
216+ std:: env:: var_os ( "PATHEXT" )
196217 }
197218
198219 #[ inline]
@@ -241,6 +262,8 @@ fn parse_path_ext(pathext: &str) -> Vec<String> {
241262 Some ( s. to_owned ( ) )
242263 } else {
243264 // Invalid segment; just ignore it.
265+ #[ cfg( feature = "tracing" ) ]
266+ tracing:: debug!( "PATHEXT segment \" {s}\" missing leading dot, ignoring" ) ;
244267 None
245268 }
246269 } )
0 commit comments