Packages

fnord

0.9.38

AI code archaeology

Current section

Files

Jump to
fnord lib util exec.ex
Raw

lib/util/exec.ex

defmodule Util.Exec do
@moduledoc """
Seam over subprocess execution for outward-facing commands that have no
dedicated facade of their own (git goes through `GitCli`; everything else
that shells out to affect the world outside the BEAM - desktop
notifications, escript installs - routes through this module). `impl/0`
resolves the `:exec` Globals key (same dispatch pattern as `:http_client`),
defaulting to the System passthrough in the sibling Default module. Tests
get the Mox mock with NO default stub, so a test that reaches an unscripted
subprocess fails loudly instead of spawning one.
"""
@doc """
Runs `executable` with `args`. Mirrors `System.cmd/3`: returns the
collected output and the exit status.
"""
@callback cmd(String.t(), [String.t()], keyword) :: {Collectable.t(), non_neg_integer()}
@doc """
Resolves `name` on the PATH. Mirrors `System.find_executable/1`.
"""
@callback find_executable(String.t()) :: String.t() | nil
def impl() do
Services.Globals.get_env(:fnord, :exec, Util.Exec.Default)
end
@spec cmd(String.t(), [String.t()], keyword) :: {Collectable.t(), non_neg_integer()}
def cmd(executable, args, opts \\ []), do: impl().cmd(executable, args, opts)
@spec find_executable(String.t()) :: String.t() | nil
def find_executable(name), do: impl().find_executable(name)
end
defmodule Util.Exec.Default do
@moduledoc false
@behaviour Util.Exec
@impl Util.Exec
def cmd(executable, args, opts), do: System.cmd(executable, args, opts)
@impl Util.Exec
def find_executable(name), do: System.find_executable(name)
end