os: fix `find_abs_path_of_executable` function (on Windows) (#14835)

master
Wertzui123 2022-06-23 02:36:15 +02:00 committed by GitHub
parent 2524207d1c
commit 587101a1ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 16 deletions

View File

@ -0,0 +1,46 @@
module os
fn test_find_abs_path_of_executable() ? {
tfolder := join_path(temp_dir(), 'v', 'tests', 'filepath_test')
rmdir_all(tfolder) or {}
assert !is_dir(tfolder)
mkdir_all(tfolder)?
defer {
rmdir_all(tfolder) or {}
}
//
original_path := getenv('PATH')
original_wdir := getwd()
defer {
chdir(original_wdir) or {}
}
//
new_path := tfolder + path_delimiter + original_path
setenv('PATH', new_path, true)
//
mut myclang_file := 'myclang'
$if windows {
myclang_file += '.bat'
}
//
chdir(tfolder)?
write_file(myclang_file, 'echo hello')?
chmod(myclang_file, 0o0777)?
dump(real_path(myclang_file))
dump(is_executable(myclang_file))
defer {
rm(myclang_file) or {}
}
//
fpath := find_abs_path_of_executable('myclang') or {
assert false
return
}
dump(fpath)
//
setenv('PATH', original_path, true)
if x := find_abs_path_of_executable('myclang') {
eprintln('> find_abs_path_of_executable should have failed, but instead it found: $x')
assert false
}
}

View File

@ -404,7 +404,7 @@ pub fn is_executable(path string) bool {
// 04 Read-only // 04 Read-only
// 06 Read and write // 06 Read and write
p := real_path(path) p := real_path(path)
return exists(p) && p.ends_with('.exe') return exists(p) && (p.ends_with('.exe') || p.ends_with('.bat'))
} }
$if solaris { $if solaris {
statbuf := C.stat{} statbuf := C.stat{}

View File

@ -12,6 +12,8 @@ pub const (
args = []string{} args = []string{}
) )
const executable_suffixes = ['']
fn get_path_delimiter() string { fn get_path_delimiter() string {
delimiter := ':' delimiter := ':'
$if js_node { $if js_node {

View File

@ -452,20 +452,26 @@ fn error_failed_to_find_executable() IError {
return IError(&ExecutableNotFoundError{}) return IError(&ExecutableNotFoundError{})
} }
// find_exe_path walks the environment PATH, just like most shell do, it returns // find_abs_path_of_executable walks the environment PATH, just like most shell do, it returns
// the absolute path of the executable if found // the absolute path of the executable if found
pub fn find_abs_path_of_executable(exepath string) ?string { pub fn find_abs_path_of_executable(exepath string) ?string {
if exepath == '' { if exepath == '' {
return error('expected non empty `exepath`') return error('expected non empty `exepath`')
} }
if is_abs_path(exepath) {
return real_path(exepath) for suffix in executable_suffixes {
fexepath := exepath + suffix
if is_abs_path(fexepath) {
return real_path(fexepath)
} }
mut res := '' mut res := ''
path := getenv('PATH') path := getenv('PATH')
paths := path.split(path_delimiter) paths := path.split(path_delimiter)
for p in paths { for p in paths {
found_abs_path := join_path_single(p, exepath) found_abs_path := join_path_single(p, fexepath)
$if trace_find_abs_path_of_executable ? {
dump(found_abs_path)
}
if exists(found_abs_path) && is_executable(found_abs_path) { if exists(found_abs_path) && is_executable(found_abs_path) {
res = found_abs_path res = found_abs_path
break break
@ -474,6 +480,7 @@ pub fn find_abs_path_of_executable(exepath string) ?string {
if res.len > 0 { if res.len > 0 {
return real_path(res) return real_path(res)
} }
}
return error_failed_to_find_executable() return error_failed_to_find_executable()
} }

View File

@ -17,6 +17,8 @@ pub const (
path_delimiter = ':' path_delimiter = ':'
) )
const executable_suffixes = ['']
const ( const (
stdin_value = 0 stdin_value = 0
stdout_value = 1 stdout_value = 1

View File

@ -14,6 +14,8 @@ fn C.CreateHardLinkW(&u16, &u16, C.SECURITY_ATTRIBUTES) int
fn C._getpid() int fn C._getpid() int
const executable_suffixes = ['.exe', '.bat', '']
pub const ( pub const (
path_separator = '\\' path_separator = '\\'
path_delimiter = ';' path_delimiter = ';'