Skip to content

Commit

Permalink
Fix dialyzer warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
akash-akya committed Sep 25, 2024
1 parent 75b2d31 commit 51f6cba
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 212 deletions.
4 changes: 2 additions & 2 deletions lib/ex_cmd.ex
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ defmodule ExCmd do
@spec stream!(nonempty_list(String.t()),
input: Enum.t() | collectable_func(),
exit_timeout: timeout(),
stderr: :console | :redirect_to_stdout | :disable | :consume,
stderr: :console | :redirect_to_stdout | :disable,
ignore_epipe: boolean(),
max_chunk_size: pos_integer()
) :: ExCmd.Stream.t()
Expand All @@ -255,7 +255,7 @@ defmodule ExCmd do
@spec stream(nonempty_list(String.t()),
input: Enum.t() | collectable_func(),
exit_timeout: timeout(),
stderr: :console | :redirect_to_stdout | :disable | :consume,
stderr: :console | :redirect_to_stdout | :disable,
ignore_epipe: boolean(),
max_chunk_size: pos_integer()
) :: ExCmd.Stream.t()
Expand Down
29 changes: 6 additions & 23 deletions lib/ex_cmd/process.ex
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ defmodule ExCmd.Process do
1. `:console` - stderr output is redirected to console (Default)
2. `:redirect_to_stdout` - stderr output is redirected to stdout
2. `:consume` - stderr output read separately, allowing you to consume it separately from stdout. See below for more details
4. `:disable` - stderr output is redirected `/dev/null` suppressing all output. See below for more details.
3. `:disable` - stderr output is redirected `/dev/null` suppressing all output. See below for more details.
### Using `redirect_to_stdout`
Expand Down Expand Up @@ -274,9 +273,9 @@ defmodule ExCmd.Process do
use GenServer

alias ExCmd.Process.Exec
alias ExCmd.Process.Proto
alias ExCmd.Process.Operations
alias ExCmd.Process.Pipe
alias ExCmd.Process.Proto
alias ExCmd.Process.State

require Logger
Expand All @@ -298,8 +297,6 @@ defmodule ExCmd.Process do

@type exit_status :: non_neg_integer

@type caller :: GenServer.from()

@default_opts [env: [], stderr: :console, log: nil]
@default_buffer_size 65_531

Expand Down Expand Up @@ -353,8 +350,6 @@ defmodule ExCmd.Process do
1. `:console` - stderr output is redirected to console (Default)
2. `:redirect_to_stdout` - stderr output is redirected to stdout
3. `:disable` - stderr output is redirected `/dev/null` suppressing all output
4. `:consume` - connects stderr for the consumption. When set, the stderr output must be consumed to
avoid external program from blocking.
See [`:stderr`](#module-stderr) for more details and issues associated with them
Expand Down Expand Up @@ -496,7 +491,8 @@ defmodule ExCmd.Process do
For more details check module documentation.
"""
@spec await_exit(t, timeout :: timeout()) :: {:ok, exit_status}
@spec await_exit(t, timeout :: timeout()) ::
{:ok, exit_status} | {:error, :killed} | {:error, term}
def await_exit(process, timeout \\ 5000) do
%__MODULE__{
monitor_ref: monitor_ref,
Expand Down Expand Up @@ -782,12 +778,7 @@ defmodule ExCmd.Process do
%{cmd_with_args: cmd_with_args, env: env} = state.args
{os_pid, port} = Proto.start(cmd_with_args, env, Map.take(state.args, [:log, :stderr, :cd]))

stderr =
if state.stderr == :consume do
Pipe.new(:stderr, port, state.owner)
else
Pipe.new(:stderr)
end
stderr = Pipe.new(:stderr)

%State{
state
Expand All @@ -806,20 +797,12 @@ defmodule ExCmd.Process do

@spec handle_command(recv_commands, binary, State.t()) :: {:noreply, State.t()}
def handle_command(tag, bin, state) when tag in [:output_eof, :output] do
# State.pipe_name_for_fd(state, read_resource)
pipe_name = :stdout

with {:ok, operation_name} <- Operations.match_pending_operation(state, pipe_name),
{:ok, {_stream, from, _}, state} <- State.pop_operation(state, operation_name) do
ret =
case {operation_name, bin} do
{:read_stdout_or_stderr, <<>>} ->
:eof

{:read_stdout_or_stderr, bin} ->
# TODO: must be stderr in case of stderr
{:ok, {:stdout, bin}}

{name, <<>>} when name in [:read_stdout, :read_stderr] ->
:eof

Expand Down Expand Up @@ -867,7 +850,7 @@ defmodule ExCmd.Process do
maybe_shutdown(state)
end

@spec close_pipes(State.t(), caller) :: State.t()
@spec close_pipes(State.t(), pid) :: State.t()
defp close_pipes(state, caller) do
state =
case Pipe.close(state.pipes.stdin, caller) do
Expand Down
16 changes: 8 additions & 8 deletions lib/ex_cmd/process/exec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defmodule ExCmd.Process.Exec do
cmd_with_args: nonempty_list(),
cd: charlist,
env: env,
stderr: :console | :redirect_to_stdout | :disable | :consume
stderr: :console | :redirect_to_stdout | :disable,
log: nil | String.t()
}}
| {:error, String.t()}
def normalize_exec_args(cmd_with_args, opts) do
Expand All @@ -28,7 +29,7 @@ defmodule ExCmd.Process.Exec do
end
end

@spec normalize_cmd(nonempty_list()) :: {:ok, nonempty_list()} | {:error, binary()}
@spec normalize_cmd(nonempty_list()) :: {:ok, nonempty_list()} | {:error, String.t()}
defp normalize_cmd(arg) do
case arg do
[cmd | _] when is_binary(cmd) ->
Expand All @@ -53,7 +54,7 @@ defmodule ExCmd.Process.Exec do
end
end

@spec normalize_cd(binary) :: {:ok, charlist()} | {:error, String.t()}
@spec normalize_cd(String.t()) :: {:ok, charlist()} | {:error, String.t()}
defp normalize_cd(cd) do
case cd do
nil ->
Expand All @@ -71,7 +72,7 @@ defmodule ExCmd.Process.Exec do
end
end

@type env :: list({String.t(), String.t()})
@type env :: [{String.t(), String.t()}]

@spec normalize_env(env) :: {:ok, env} | {:error, String.t()}
defp normalize_env(env) do
Expand All @@ -92,8 +93,8 @@ defmodule ExCmd.Process.Exec do
end
end

@spec normalize_stderr(stderr :: :console | :redirect_to_stdout | :disable | :consume | nil) ::
{:ok, :console | :redirect_to_stdout | :disable | :consume} | {:error, String.t()}
@spec normalize_stderr(stderr :: :console | :redirect_to_stdout | :disable | nil) ::
{:ok, :console | :redirect_to_stdout | :disable} | {:error, String.t()}
defp normalize_stderr(stderr) do
case stderr do
nil ->
Expand All @@ -103,8 +104,7 @@ defmodule ExCmd.Process.Exec do
{:ok, stderr}

_ ->
{:error,
":stderr must be an atom and one of :redirect_to_stdout, :console, :disable, :consume"}
{:error, ":stderr must be an atom and one of :redirect_to_stdout, :console, :disable"}
end
end

Expand Down
103 changes: 11 additions & 92 deletions lib/ex_cmd/process/operations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,25 @@ defmodule ExCmd.Process.Operations do
@type t :: %__MODULE__{
write_stdin: write_operation() | nil,
read_stdout: read_operation() | nil,
read_stderr: read_operation() | nil,
read_stdout_or_stderr: read_any_operation() | nil
read_stderr: read_operation() | nil
}

defstruct [:write_stdin, :read_stdout, :read_stderr, :read_stdout_or_stderr]
defstruct [:write_stdin, :read_stdout, :read_stderr]

@spec new :: t
def new, do: %__MODULE__{}

@type write_operation ::
{:write_stdin, GenServer.from(), binary}
| {:write_stdin, :demand}
| {:write_stdin, :demand, nil}

@type read_operation ::
{:read_stdout, GenServer.from(), binary}
| {:read_stderr, GenServer.from(), binary}
{:read_stdout, GenServer.from(), non_neg_integer}
| {:read_stderr, GenServer.from(), non_neg_integer}

@type read_any_operation ::
{:read_stdout_or_stderr, GenServer.from(), binary}
@type operation :: write_operation() | read_operation()

@type operation :: write_operation() | read_operation() | read_any_operation()

@type name :: :write_stdin | :read_stdout | :read_stderr | :read_stdout_or_stderr
@type name :: :write_stdin | :read_stdout | :read_stderr

@spec get(t, name) :: {:ok, operation()} | {:error, term}
def get(operations, name) do
Expand All @@ -54,24 +50,6 @@ defmodule ExCmd.Process.Operations do
end
end

@spec read_any(State.t(), read_any_operation()) ::
:eof
| {:noreply, State.t()}
| {:ok, {:stdout | :stderr, binary}}
| {:error, term}
def read_any(state, {:read_stdout_or_stderr, _from, _size} = operation) do
with {:ok, {_name, {caller, _}, arg}} <- validate_read_any_operation(operation),
first <- pipe_name(operation),
{:ok, primary} <- State.pipe(state, first),
second <- if(first == :stdout, do: :stderr, else: :stdout),
{:ok, secondary} <- State.pipe(state, second),
{:error, :eagain} <- do_read_any(caller, arg, primary, secondary),
{:ok, new_state} <- State.put_operation(state, operation) do
# dbg(new_state)
{:noreply, new_state}
end
end

@spec read(State.t(), read_operation()) ::
:eof
| {:noreply, State.t()}
Expand All @@ -94,23 +72,9 @@ defmodule ExCmd.Process.Operations do
def write(state, operation) do
with {:ok, {_name, {caller, _}, bin}} <- validate_write_operation(operation),
pipe_name <- pipe_name(operation),
{:ok, pipe} <- State.pipe(state, pipe_name) do
case Pipe.write(pipe, bin, caller) do
{:ok, remaining} ->
handle_successful_write(state, remaining, operation)

{:error, :eagain} ->
case State.put_operation(state, operation) do
{:ok, new_state} ->
{:noreply, new_state}

error ->
error
end

ret ->
ret
end
{:ok, pipe} <- State.pipe(state, pipe_name),
{:ok, remaining} <- Pipe.write(pipe, bin, caller) do
handle_successful_write(state, remaining, operation)
end
end

Expand Down Expand Up @@ -164,10 +128,6 @@ defmodule ExCmd.Process.Operations do
# credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
def match_pending_operation(state, pipe_name) do
cond do
state.operations.read_stdout_or_stderr &&
pipe_name in [:stdout, :stderr] ->
{:ok, :read_stdout_or_stderr}

state.operations.read_stdout &&
pipe_name == :stdout ->
{:ok, :read_stdout}
Expand Down Expand Up @@ -202,45 +162,6 @@ defmodule ExCmd.Process.Operations do
end
end

@spec do_read_any(pid, non_neg_integer(), Pipe.t(), Pipe.t()) ::
:eof | {:ok, {Pipe.name(), binary}} | {:error, term}
defp do_read_any(caller, size, primary, secondary) do
case Pipe.read(primary, size, caller) do
ret1 when ret1 in [:eof, {:error, :eagain}, {:error, :pipe_closed_or_invalid_caller}] ->
case {ret1, Pipe.read(secondary, size, caller)} do
{:eof, :eof} ->
:eof

{_, {:ok, bin}} ->
{:ok, {secondary.name, bin}}

{ret1, {:error, :pipe_closed_or_invalid_caller}} ->
ret1

{_, ret2} ->
ret2
end

{:ok, bin} ->
{:ok, {primary.name, bin}}

ret1 ->
ret1
end
end

@spec validate_read_any_operation(operation) ::
{:ok, read_any_operation()} | {:error, :invalid_operation}
defp validate_read_any_operation(operation) do
case operation do
{:read_stdout_or_stderr, _from, size} when is_integer(size) and size >= 0 ->
{:ok, operation}

_ ->
{:error, :invalid_operation}
end
end

@spec validate_read_operation(operation) ::
{:ok, read_operation()} | {:error, :invalid_operation}
defp validate_read_operation(operation) do
Expand Down Expand Up @@ -273,8 +194,7 @@ defmodule ExCmd.Process.Operations do

@spec validate_operation(operation) :: {:ok, operation()} | {:error, :invalid_operation}
defp validate_operation(operation) do
with {:error, :invalid_operation} <- validate_read_operation(operation),
{:error, :invalid_operation} <- validate_read_any_operation(operation) do
with {:error, :invalid_operation} <- validate_read_operation(operation) do
validate_write_operation(operation)
end
end
Expand All @@ -285,7 +205,6 @@ defmodule ExCmd.Process.Operations do
:write_stdin -> :stdin
:read_stdout -> :stdout
:read_stderr -> :stderr
:read_stdout_or_stderr -> :stdout
end
end
end
Loading

0 comments on commit 51f6cba

Please sign in to comment.