@@ -26,7 +26,7 @@ pub(crate) fn resolve_executable_in_env(
2626 }
2727
2828 if contains_path_separator ( command) {
29- if Path :: new ( command) . is_file ( ) {
29+ if path_is_existing_file ( Path :: new ( command) ) {
3030 return Ok ( command. to_string ( ) ) ;
3131 }
3232 bail ! ( "secretBackendCommand '{command}' does not exist" ) ;
@@ -46,7 +46,7 @@ pub(crate) fn resolve_executable_in_env(
4646 for ext in & extensions {
4747 let candidate_name = format ! ( "{command}{ext}" ) ;
4848 let candidate = dir. join ( & candidate_name) ;
49- if candidate . is_file ( ) {
49+ if path_is_existing_file ( & candidate ) {
5050 return Ok ( candidate. to_string_lossy ( ) . into_owned ( ) ) ;
5151 }
5252 }
@@ -55,6 +55,30 @@ pub(crate) fn resolve_executable_in_env(
5555 bail ! ( "secretBackendCommand '{command}' does not exist" ) ;
5656}
5757
58+ fn path_is_existing_file ( path : & Path ) -> bool {
59+ if path. is_file ( ) {
60+ return true ;
61+ }
62+ #[ cfg( windows) ]
63+ {
64+ let Some ( name) = path. file_name ( ) else {
65+ return false ;
66+ } ;
67+ let Some ( parent) = path. parent ( ) else {
68+ return false ;
69+ } ;
70+ let Ok ( entries) = std:: fs:: read_dir ( parent) else {
71+ return false ;
72+ } ;
73+ return entries. flatten ( ) . any ( |entry| {
74+ entry. file_name ( ) . eq_ignore_ascii_case ( name)
75+ && entry. file_type ( ) . is_ok_and ( |t| t. is_file ( ) )
76+ } ) ;
77+ }
78+ #[ cfg( not( windows) ) ]
79+ false
80+ }
81+
5882fn contains_path_separator ( command : & str ) -> bool {
5983 command. contains ( '\\' ) || command. contains ( '/' )
6084}
@@ -100,7 +124,7 @@ fn pathext_extensions(env: &HashMap<String, String>) -> Vec<String> {
100124fn find_on_path ( command : & str , path_dirs : & [ PathBuf ] ) -> Option < String > {
101125 for dir in path_dirs {
102126 let candidate = dir. join ( command) ;
103- if candidate . is_file ( ) {
127+ if path_is_existing_file ( & candidate ) {
104128 return Some ( candidate. to_string_lossy ( ) . into_owned ( ) ) ;
105129 }
106130 }
0 commit comments