os: fix `find_abs_path_of_executable` function (on Windows) (#14835)
parent
2524207d1c
commit
587101a1ea
|
@ -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
|
||||
}
|
||||
}
|
|
@ -404,7 +404,7 @@ pub fn is_executable(path string) bool {
|
|||
// 04 Read-only
|
||||
// 06 Read and write
|
||||
p := real_path(path)
|
||||
return exists(p) && p.ends_with('.exe')
|
||||
return exists(p) && (p.ends_with('.exe') || p.ends_with('.bat'))
|
||||
}
|
||||
$if solaris {
|
||||
statbuf := C.stat{}
|
||||
|
|
|
@ -12,6 +12,8 @@ pub const (
|
|||
args = []string{}
|
||||
)
|
||||
|
||||
const executable_suffixes = ['']
|
||||
|
||||
fn get_path_delimiter() string {
|
||||
delimiter := ':'
|
||||
$if js_node {
|
||||
|
|
37
vlib/os/os.v
37
vlib/os/os.v
|
@ -452,27 +452,34 @@ fn error_failed_to_find_executable() IError {
|
|||
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
|
||||
pub fn find_abs_path_of_executable(exepath string) ?string {
|
||||
if exepath == '' {
|
||||
return error('expected non empty `exepath`')
|
||||
}
|
||||
if is_abs_path(exepath) {
|
||||
return real_path(exepath)
|
||||
}
|
||||
mut res := ''
|
||||
path := getenv('PATH')
|
||||
paths := path.split(path_delimiter)
|
||||
for p in paths {
|
||||
found_abs_path := join_path_single(p, exepath)
|
||||
if exists(found_abs_path) && is_executable(found_abs_path) {
|
||||
res = found_abs_path
|
||||
break
|
||||
|
||||
for suffix in executable_suffixes {
|
||||
fexepath := exepath + suffix
|
||||
if is_abs_path(fexepath) {
|
||||
return real_path(fexepath)
|
||||
}
|
||||
mut res := ''
|
||||
path := getenv('PATH')
|
||||
paths := path.split(path_delimiter)
|
||||
for p in paths {
|
||||
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) {
|
||||
res = found_abs_path
|
||||
break
|
||||
}
|
||||
}
|
||||
if res.len > 0 {
|
||||
return real_path(res)
|
||||
}
|
||||
}
|
||||
if res.len > 0 {
|
||||
return real_path(res)
|
||||
}
|
||||
return error_failed_to_find_executable()
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ pub const (
|
|||
path_delimiter = ':'
|
||||
)
|
||||
|
||||
const executable_suffixes = ['']
|
||||
|
||||
const (
|
||||
stdin_value = 0
|
||||
stdout_value = 1
|
||||
|
|
|
@ -14,6 +14,8 @@ fn C.CreateHardLinkW(&u16, &u16, C.SECURITY_ATTRIBUTES) int
|
|||
|
||||
fn C._getpid() int
|
||||
|
||||
const executable_suffixes = ['.exe', '.bat', '']
|
||||
|
||||
pub const (
|
||||
path_separator = '\\'
|
||||
path_delimiter = ';'
|
||||
|
|
Loading…
Reference in New Issue