Module: Toys::StandardMixins::Exec

Includes:
Mixin
Defined in:
lib/toys/standard_mixins/exec.rb

Overview

A set of helper methods for invoking subcommands. Provides shortcuts for common cases such as invoking Ruby in a subprocess or capturing output in a string. Also provides an interface for controlling a spawned process's streams.

You may make these methods available to your tool by including the following directive in your tool configuration:

include :exec

This is a frontend for Utils::Exec. More information is available in that class's documentation.

Configuration Options

Subprocesses may be configured using the options in the Utils::Exec class. These include a variety of options supported by Process#spawn, and some options supported by Utils::Exec itself.

You can set default configuration by passing options to the include directive. For example, to log commands at the debug level for all subprocesses spawned by this tool:

include :exec, log_level: Logger::DEBUG

Two special options are also recognized by the mixin.

  • A :result_callback proc may take a second argument. If it does, the context object is passed as the second argument. This is useful if a :result_callback is applied to the entire tool by passing it to the include directive. In that case, self is not set to the context object as it normally would be in a tool's run method, so you cannot access it otherwise. For example, here is how to log the exit code for every subcommand:

    tool "mytool" do
      callback = proc do |result, context|
        context.logger.info "Exit code: #{result.exit_code}"
      end
      include :exec, result_callback: callback  # ...
    
    end
    

    You may also pass a symbol as the :result_callback. The method with that name is then called as the callback. The method must take one argument, the result object.

  • If :exit_on_nonzero_status is set to true, a nonzero exit code returned by the subprocess will also cause the tool to exit immediately with that same code.

    This is particularly useful as an option to the include directive, where it causes any subprocess failure to abort the tool, similar to setting set -e in a bash script.

    include :exec, exit_on_nonzero_status: true
    

    :e can be used as a shortcut for :exit_on_nonzero_status

    include :exec, e: true
    

Constant Summary collapse

KEY =

Context key for the executor object.

Returns:

  • (Object)
::Object.new.freeze

Instance Method Summary collapse

Methods included from Mixin

create

Instance Method Details

#capture(cmd, **opts) {|controller| ... } ⇒ String

Execute a command. The command may be given as a single string to pass to a shell, or an array of strings indicating a posix command.

Captures standard out and returns it as a string. Cannot be run in the background.

If a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • cmd (String, Array<String>)

    The command to execute.

  • opts (keywords)

    The command options. All options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:

  • (String)

    What was written to standard out.



242
243
244
245
# File 'lib/toys/standard_mixins/exec.rb', line 242

def capture(cmd, **opts, &block)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].capture(cmd, **opts, &block)
end

#capture_proc(func, **opts) {|controller| ... } ⇒ String

Execute a proc in a subprocess.

Captures standard out and returns it as a string. Cannot be run in the background.

If a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • func (Proc)

    The proc to call.

  • opts (keywords)

    The command options. Most options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:

  • (String)

    What was written to standard out.



288
289
290
291
# File 'lib/toys/standard_mixins/exec.rb', line 288

def capture_proc(func, **opts, &block)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].capture_proc(func, **opts, &block)
end

#capture_ruby(args, **opts) {|controller| ... } ⇒ String

Spawn a ruby process and pass the given arguments to it.

Captures standard out and returns it as a string. Cannot be run in the background.

If a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • args (String, Array<String>)

    The arguments to ruby.

  • opts (keywords)

    The command options. All options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:

  • (String)

    What was written to standard out.



265
266
267
268
# File 'lib/toys/standard_mixins/exec.rb', line 265

def capture_ruby(args, **opts, &block)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].capture_ruby(args, **opts, &block)
end

#capture_tool(cmd, **opts) {|controller| ... } ⇒ String

Execute a tool. The command may be given as a single string or an array of strings, representing the tool to run and the arguments to pass.

Captures standard out and returns it as a string. Cannot be run in the background.

If a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • cmd (String, Array<String>)

    The tool to execute.

  • opts (keywords)

    The command options. Most options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:

  • (String)

    What was written to standard out.



312
313
314
315
316
# File 'lib/toys/standard_mixins/exec.rb', line 312

def capture_tool(cmd, **opts, &block)
  func = Exec._make_tool_caller(cmd)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].capture_proc(func, **opts, &block)
end

#configure_exec(**opts) ⇒ self

Set default configuration keys.

All options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Parameters:

  • opts (keywords)

    The default options.

Returns:

  • (self)


121
122
123
124
125
# File 'lib/toys/standard_mixins/exec.rb', line 121

def configure_exec(**opts)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].configure_defaults(**opts)
  self
end

#exec(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result

Execute a command. The command may be given as a single string to pass to a shell, or an array of strings indicating a posix command.

If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • cmd (String, Array<String>)

    The command to execute.

  • opts (keywords)

    The command options. All options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:



146
147
148
149
# File 'lib/toys/standard_mixins/exec.rb', line 146

def exec(cmd, **opts, &block)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].exec(cmd, **opts, &block)
end

#exec_proc(func, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result

Execute a proc in a subprocess.

If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • func (Proc)

    The proc to call.

  • opts (keywords)

    The command options. Most options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:



193
194
195
196
# File 'lib/toys/standard_mixins/exec.rb', line 193

def exec_proc(func, **opts, &block)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].exec_proc(func, **opts, &block)
end

#exec_ruby(args, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result Also known as: ruby

Spawn a ruby process and pass the given arguments to it.

If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • args (String, Array<String>)

    The arguments to ruby.

  • opts (keywords)

    The command options. All options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:



169
170
171
172
# File 'lib/toys/standard_mixins/exec.rb', line 169

def exec_ruby(args, **opts, &block)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].exec_ruby(args, **opts, &block)
end

#exec_tool(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result

Execute a tool. The command may be given as a single string or an array of strings, representing the tool to run and the arguments to pass.

If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • cmd (String, Array<String>)

    The tool to execute.

  • opts (keywords)

    The command options. Most options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:



217
218
219
220
221
# File 'lib/toys/standard_mixins/exec.rb', line 217

def exec_tool(cmd, **opts, &block)
  func = Exec._make_tool_caller(cmd)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].exec_proc(func, **opts, &block)
end

#exit_on_nonzero_status(status) ⇒ Integer

Exit if the given status code is nonzero. Otherwise, returns 0.

Parameters:

Returns:

  • (Integer)


345
346
347
348
349
350
# File 'lib/toys/standard_mixins/exec.rb', line 345

def exit_on_nonzero_status(status)
  status = status.exit_code if status.respond_to?(:exit_code)
  status = status.exitstatus if status.respond_to?(:exitstatus)
  Context.exit(status) unless status.zero?
  0
end

#sh(cmd, **opts) {|controller| ... } ⇒ Integer

Execute the given string in a shell. Returns the exit code. Cannot be run in the background.

If a block is provided, a Utils::Exec::Controller will be yielded to it.

Parameters:

  • cmd (String)

    The shell command to execute.

  • opts (keywords)

    The command options. All options listed in the Utils::Exec documentation are supported, plus the exit_on_nonzero_status option.

Yield Parameters:

Returns:

  • (Integer)

    The exit code



334
335
336
337
# File 'lib/toys/standard_mixins/exec.rb', line 334

def sh(cmd, **opts, &block)
  opts = Exec._setup_exec_opts(opts, self)
  self[KEY].sh(cmd, **opts, &block)
end