diff --git a/lib/elixir/lib/port.ex b/lib/elixir/lib/port.ex index 6d1df7196b..0ba915ddde 100644 --- a/lib/elixir/lib/port.ex +++ b/lib/elixir/lib/port.ex @@ -124,9 +124,9 @@ defmodule Port do Spawn executable is a more restricted and explicit version of spawn. It expects full file paths to the executable you want to execute. If they are in your `$PATH`, - they can be retrieved by calling `System.find_executable/1`: + they can be retrieved by calling `System.find_executable!/1`: - iex> path = System.find_executable("echo") + iex> path = System.find_executable!("echo") iex> port = Port.open({:spawn_executable, path}, [:binary, args: ["hello world"]]) iex> flush() {#Port<0.1380>, {:data, "hello world\n"}} diff --git a/lib/elixir/lib/system.ex b/lib/elixir/lib/system.ex index 3609406587..d93d036e58 100644 --- a/lib/elixir/lib/system.ex +++ b/lib/elixir/lib/system.ex @@ -630,8 +630,19 @@ defmodule System do operating systems. It also considers the proper executable extension for each operating system, so for Windows it will try to lookup files with `.com`, `.cmd` or similar extensions. + + See also `find_executable!/1`. + + ## Examples + + System.find_executable("bash") + #=> "/bin/bash" + + System.find_executable("unknown") + #=> nil + """ - @spec find_executable(binary) :: binary | nil + @spec find_executable(binary()) :: binary() | nil def find_executable(program) when is_binary(program) do assert_no_null_byte!(program, "System.find_executable/1") @@ -641,6 +652,27 @@ defmodule System do end end + @doc """ + Locates an executable on the system or raises an error. + + See also `find_executable/1`. + + ## Examples + + System.find_executable!("bash") + #=> "/bin/bash" + + System.find_executable!("unknown") + ** (RuntimeError) could not find executable "unknown" in PATH + + """ + @doc since: "1.20.0" + @spec find_executable!(binary()) :: binary() + def find_executable!(program) when is_binary(program) do + find_executable(program) || + raise "could not find executable #{inspect(program)} in PATH" + end + @doc """ Returns all system environment variables. diff --git a/lib/elixir/test/elixir/system_test.exs b/lib/elixir/test/elixir/system_test.exs index b6d56dec77..d2f871c05d 100644 --- a/lib/elixir/test/elixir/system_test.exs +++ b/lib/elixir/test/elixir/system_test.exs @@ -126,7 +126,7 @@ defmodule SystemTest do test "cmd/3 with absolute and relative paths", config do echo = Path.join(config.tmp_dir, @echo) File.mkdir_p!(Path.dirname(echo)) - File.ln_s!(System.find_executable("cmd"), echo) + File.ln_s!(System.find_executable!("cmd"), echo) File.cd!(Path.dirname(echo), fn -> # There is a bug in OTP where find_executable is finding @@ -210,7 +210,7 @@ defmodule SystemTest do test "cmd/3 with absolute and relative paths", config do echo = Path.join(config.tmp_dir, @echo) File.mkdir_p!(Path.dirname(echo)) - File.ln_s!(System.find_executable("echo"), echo) + File.ln_s!(System.find_executable!("echo"), echo) File.cd!(Path.dirname(echo), fn -> # There is a bug in OTP where find_executable is finding