From ebe2c7b45832f41e75deb73d784f05ebc87c9b71 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Fri, 11 Jan 2019 15:59:03 +0100 Subject: [PATCH] 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. --- common/mlstdutils/std_utils.ml | 29 ++++++++++++++++------------ common/mlstdutils/std_utils.mli | 5 ++++- common/mlstdutils/std_utils_tests.ml | 10 ++++++++++ 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml index 5a92dccc9..70156d1ba 100644 --- a/common/mlstdutils/std_utils.ml +++ b/common/mlstdutils/std_utils.ml @@ -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 diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli index ca4e940cf..5e5242f7a 100644 --- a/common/mlstdutils/std_utils.mli +++ b/common/mlstdutils/std_utils.mli @@ -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. *) diff --git a/common/mlstdutils/std_utils_tests.ml b/common/mlstdutils/std_utils_tests.ml index f7b0247a4..d161b5e7e 100644 --- a/common/mlstdutils/std_utils_tests.ml +++ b/common/mlstdutils/std_utils_tests.ml @@ -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. *)