mlstdutils: allow relative/absolute paths for Std_utils.which

Make Std_utils.which behave a bit more like which(1), checking the
existance of relative/absolute paths specified.
This commit is contained in:
Pino Toscano
2019-01-11 15:59:03 +01:00
parent 88a754bd07
commit ebe2c7b458
3 changed files with 31 additions and 13 deletions

View File

@@ -610,18 +610,23 @@ let failwithf fs = ksprintf failwith fs
exception Executable_not_found of string (* executable *)
let which executable =
let paths =
try String.nsplit ":" (Sys.getenv "PATH")
with Not_found -> [] in
let paths = List.filter_map (
fun p ->
let path = p // executable in
try Unix.access path [Unix.X_OK]; Some path
with Unix.Unix_error _ -> None
) paths in
match paths with
| [] -> raise (Executable_not_found executable)
| x :: _ -> x
if String.find executable Filename.dir_sep <> -1 then (
try Unix.access executable [Unix.X_OK]; executable
with Unix.Unix_error _ -> raise (Executable_not_found executable)
) else (
let paths =
try String.nsplit ":" (Sys.getenv "PATH")
with Not_found -> [] in
let paths = List.filter_map (
fun p ->
let path = p // executable in
try Unix.access path [Unix.X_OK]; Some path
with Unix.Unix_error _ -> None
) paths in
match paths with
| [] -> raise (Executable_not_found executable)
| x :: _ -> x
)
(* Program name. *)
let prog = Filename.basename Sys.executable_name

View File

@@ -359,7 +359,10 @@ exception Executable_not_found of string (* executable *)
in [$PATH]. *)
val which : string -> string
(** Return the full path of the specified executable from [$PATH].
(** Return the full path of the specified executable from [$PATH],
in case it is only a name. In case of a relative or absolute path
(i.e. more than just a name), return the same path specified if
exists.
Throw [Executable_not_found] if not available. *)

View File

@@ -149,6 +149,16 @@ let test_string_chomp ctx =
let test_which ctx =
assert_nonempty_string (which "true");
assert_raises_executable_not_found "this-command-does-not-really-exist";
begin
let exe_name = "true" in
let exe = which exe_name in
assert_equal_string exe (which exe);
with_bracket_chdir ctx (Filename.dirname exe) (
fun ctx ->
let exe_relative = "./" ^ exe_name in
assert_equal_string exe_relative (which exe_relative)
)
end;
()
(* Suites declaration. *)