Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions spec/std/process_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,20 @@ describe Process do
end
end

describe ".run (args)" do
it "waits for the process" do
Process.run(to_ary(exit_code_command(0))).exit_code.should eq(0)
end

it "waits for the process" do
Process.run(to_ary(exit_code_command(0))) { }[0].exit_code.should eq(0)
end

it "returns block result" do
Process.run(to_ary(exit_code_command(0))) { 42 }[1].should eq 42
end
end

describe ".run" do
it "waits for the process" do
Process.run(*exit_code_command(0)).exit_code.should eq(0)
Expand Down
59 changes: 59 additions & 0 deletions src/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,29 @@ class Process
alias ExecStdio = Redirect | IO::FileDescriptor
alias Env = Nil | Hash(String, Nil) | Hash(String, String?) | Hash(String, String)

# Executes a child process and waits for it to complete, returning its status.
#
# See `Process.new` for the meaning of the parameters.
#
# Returns a `Process::Status` representing the child process' exit status.
#
# Raises `IO::Error` if the execution itself fails (for example because the
# executable does not exist or is not executable).
#
# Example:
#
# ```
# io = IO::Memory.new
# status = Process.run(%w[echo hello], output: io)
# io.to_s # => "hello\n"
# status # => Process::Status[0]
# ```
def self.run(args : Enumerable(String), *, env : Env = nil, clear_env : Bool = false,
input : Stdio = Redirect::Close, output : Stdio = Redirect::Close, error : Stdio = Redirect::Close, chdir : Path | String? = nil) : Process::Status
status = new(args, env: env, clear_env: clear_env, input: input, output: output, error: error, chdir: chdir).wait
status
end

# Executes a child process and waits for it to complete, returning its status.
#
# See `Process.new` for the meaning of the parameters.
Expand All @@ -202,6 +225,42 @@ class Process
status
end

# Executes a child process, yields the block, and then waits for it to finish.
#
# See `Process.new` for the meaning of the parameters.
#
# By default the process is configured to use pipes for input, output and error.
# These will be closed automatically at the end of the block.
#
# Returns a tuple with the process' exit status and the block's output value.
#
# Raises `IO::Error` if the execution itself fails (for example because the
# executable does not exist or is not executable).
#
# Example:
#
# ```
# status, result = Process.run(%w[echo hello]) do |process|
# process.output.gets_to_end
# end
# status # => Process::Status[0]
# result # => "hello\n"
# ```
def self.run(args : Enumerable(String), *, env : Env = nil, clear_env : Bool = false,
input : Stdio = Redirect::Pipe, output : Stdio = Redirect::Pipe, error : Stdio = Redirect::Pipe, chdir : Path | String? = nil, & : Process -> _)
process = new(args, env: env, clear_env: clear_env, input: input, output: output, error: error, chdir: chdir)
begin
value = yield process

process.close
status = process.wait
{status, value}
rescue ex
process.terminate
raise ex
end
end

# Executes a child process, yields the block, and then waits for it to finish.
#
# See `Process.new` for the meaning of the parameters.
Expand Down
Loading