diff --git a/executable/Exec.re b/executable/Exec.re new file mode 100644 index 000000000..0629889fa --- /dev/null +++ b/executable/Exec.re @@ -0,0 +1,30 @@ +open Fnm; + +let startsWith = (~prefix, str) => + Base.String.prefix(str, String.length(prefix)) != prefix; + +let run = (~cmd) => { + let fnmPath = Filename.concat(Directories.currentVersion, "bin"); + let path = Opt.(Sys.getenv_opt("PATH") or ""); + let pathEnv = Printf.sprintf("PATH=%s:%s", fnmPath, path); + let env = + Unix.environment() + |> Array.copy + |> Base.Array.filter(~f=startsWith(~prefix="PATH=")) + |> Array.append([|pathEnv|]); + let%lwt exitCode = + Lwt_process.exec( + ~stdin=`Keep, + ~stdout=`Keep, + ~stderr=`Keep, + ~env, + ("", cmd), + ); + + switch (exitCode) { + | Unix.WEXITED(0) => Lwt.return_ok() + | Unix.WEXITED(x) + | Unix.WSTOPPED(x) + | Unix.WSIGNALED(x) => Lwt.return_error(x) + }; +}; diff --git a/executable/FnmApp.re b/executable/FnmApp.re index c6281563f..fb6dad123 100644 --- a/executable/FnmApp.re +++ b/executable/FnmApp.re @@ -11,6 +11,7 @@ let runCmd = lwt => { }; module Commands = { + let exec = cmd => Exec.run(~cmd=Array.of_list(cmd)) |> runCmd; let use = (version, quiet) => Use.run(~version, ~quiet) |> runCmd; let alias = (version, name) => Alias.run(~name, ~version) |> runCmd; let default = version => Alias.run(~name="default", ~version) |> runCmd; @@ -233,6 +234,30 @@ let alias = { ); }; +let exec = { + let doc = "Execute a binary with the current Node.js in the PATH"; + let man = help_secs; + let sdocs = Manpage.s_common_options; + + let command = { + let doc = "The $(docv) to execute"; + Arg.(non_empty & pos_all(string, []) & info([], ~docv="COMMAND", ~doc)); + }; + + ( + Term.(const(Commands.exec) $ command), + Term.info( + "exec", + ~envs, + ~version, + ~doc, + ~exits=Term.default_exits, + ~man, + ~sdocs, + ), + ); +}; + let default = { let doc = "Alias a version as default"; let man = help_secs; @@ -378,7 +403,17 @@ let argv = let _ = Term.eval_choice( defaultCmd, - [install, uninstall, use, alias, default, listLocal, listRemote, env], + [ + install, + uninstall, + use, + alias, + default, + listLocal, + listRemote, + env, + exec, + ], ~argv, ) |> Term.exit; diff --git a/test/TestListRemote.re b/test/TestListRemote.re index b6f252889..b1f9cda99 100644 --- a/test/TestListRemote.re +++ b/test/TestListRemote.re @@ -57,7 +57,7 @@ let allVersions6_11 = [ "v6.11.5", ]; -describe("List Remote", ({test}) => { +describe("List Remote", ({test, _}) => { let versionRegExp = Str.regexp(".*[0-9]+\\.[0-9]+\\.[0-9]+\\|.*latest-*"); let filterVersionNumbers = response =>