Class: Command::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/command/runner.rb,
lib/command/runner/message.rb,
lib/command/runner/version.rb,
lib/command/runner/backends.rb,
lib/command/runner/exceptions.rb,
lib/command/runner/backends/ssh.rb,
lib/command/runner/backends/fake.rb,
lib/command/runner/backends/spawn.rb,
lib/command/runner/backends/backticks.rb,
lib/command/runner/backends/unsafe_fake.rb,
lib/command/runner/backends/posix_spawn.rb

Overview

This handles the execution of commands.

Defined Under Namespace

Modules: Backends Classes: Message, NoCommandError, NotAvailableBackendError

Constant Summary collapse

VERSION =

The current version of Runner.

"0.9.2".freeze

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command, arguments, options = {}) ⇒ Runner

Initialize the messenger.

Parameters:

  • command (String)

    the name of the command file to run.

  • arguments (String)

    the arguments to pass to the command. may contain interpolated values, like {key} or {{key}}.

  • options (Hash) (defaults to: {})

    the options for the messenger.


81
82
83
84
85
# File 'lib/command/runner.rb', line 81

def initialize(command, arguments, options = {})
  @command = command
  @arguments = arguments
  @options = options
end

Class Attribute Details

.backend#call

Gets the default backend to use with the messenger. Defaults to the best available backend.

Returns:

  • (#call)

    a backend to use.


20
21
22
# File 'lib/command/runner.rb', line 20

def backend
  @backend ||= best_backend
end

Instance Attribute Details

#argumentsString (readonly)

The arguments the messenger was initialized with.

Returns:

  • (String)

51
52
53
# File 'lib/command/runner.rb', line 51

def arguments
  @arguments
end

#backend#call

Gets the backend to be used by the messenger. If it is not defined on the instance, it'll get the class default.

Returns:

  • (#call)

    a backend to use.

See Also:


67
68
69
# File 'lib/command/runner.rb', line 67

def backend
  @backend || self.class.backend
end

#commandString (readonly)

The command the messenger was initialized with.

Returns:

  • (String)

46
47
48
# File 'lib/command/runner.rb', line 46

def command
  @command
end

#optionsHash (readonly)

The options the messenger was initialized with.

Returns:

  • (Hash)

58
59
60
# File 'lib/command/runner.rb', line 58

def options
  @options.dup.freeze
end

Class Method Details

.best_backend(force_unsafe = false) ⇒ #call

Returns the best backend for messenger to use.

Returns:

  • (#call)

    a backend to use.


27
28
29
30
31
32
33
34
35
36
37
# File 'lib/command/runner.rb', line 27

def best_backend(force_unsafe = false)
  if Backends::PosixSpawn.available?(force_unsafe)
    Backends::PosixSpawn.new
  elsif Backends::Spawn.available?(force_unsafe)
    Backends::Spawn.new
  elsif Backends::Backticks.available?(force_unsafe)
    Backends::Backticks.new
  else
    Backends::Fake.new
  end
end

Instance Method Details

#contents(interops = {}) ⇒ Array<(String, String)>

The command line being run by the runner. Interpolates the arguments with the given interpolations.

Parameters:

  • interops (Hash) (defaults to: {})

    the interpolations to make.

Returns:

  • (Array<(String, String)>)

    the command line that will be run.

See Also:


150
151
152
# File 'lib/command/runner.rb', line 150

def contents(interops = {})
  [command, interpolate(arguments, interops)]
end

#force_unsafe!void

This method returns an undefined value.

Whether or not to force an unsafe backend. This should only be used in cases where the developer wants the arguments passed to a shell, so that the unsafe interpolated arguments can be shell'd.


140
141
142
# File 'lib/command/runner.rb', line 140

def force_unsafe!
  @unsafe = true
end

#interpolate(string, interops = {}) ⇒ Array<String>

Interpolates the given string with the given interpolations. The keys of the interpolations should be alphanumeric, including underscores and dashes. It will search the given string for {key} and {{key}}; if it finds the former, it replaces it with the escaped value. If it finds the latter, it replaces it with the value directly.

Parameters:

  • string (String)

    the string to interpolate.

  • interops (Hash) (defaults to: {})

    the interpolations to make.

Returns:

  • (Array<String>)

    the interpolated string.


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/command/runner.rb', line 164

def interpolate(string, interops = {})
  interops = Hashie::Mash.new(interops)
  args = string.shellsplit

  args.map do |arg|
    arg.gsub(/(\{{1,2})([0-9a-zA-Z_\-.]+)(\}{1,2})/) do |m|
      if $1.length != $3.length
        next m
      end

      ops = interops
      parts = $2.split('.')
      parts.each do |part|
        if ops.key?(part)
          ops = ops[part]
        else
          ops = nil
          break
        end
      end

      if ops == nil
        m
      elsif $1.length == 1
        escape(ops)
      else
        ops
      end
    end
  end
end

#pass(interops = {}, options = {}) {|Message| ... } ⇒ Message, Object Also known as: run

Runs the command and arguments with the given interpolations; defaults to no interpolations. Calls #pass!, but does not raise an error.

Parameters:

  • interops (Hash<Symbol, Object>) (defaults to: {})

    the interpolations to make.

  • options (Hash<Symbol, Object>) (defaults to: {})

    the options for the backend.

Yields:

  • (Message)

    when the command finishes.

Returns:

  • (Message, Object)

    message if no block was given, the return value of the block otherwise.


119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/command/runner.rb', line 119

def pass(interops = {}, options = {}, &block)
  pass! interops, options, &block

rescue NoCommandError
  message = Message.error(contents(interops).join(' '))

  if block_given?
    block.call(message)
  else
    message
  end
end

#pass!(interops = {}, options = {}) {|Message| ... } ⇒ Message, Object Also known as: run!

Note:

This method may not raise a NoCommandError and instead return a Message with the error code 127, even if the command doesn't exist.

Runs the command and arguments with the given interpolations; defaults to no interpolations.

Parameters:

  • interops (Hash<Symbol, Object>) (defaults to: {})

    the interpolations to make.

  • options (Hash<Symbol, Object>) (defaults to: {})

    the options for the backend.

Yields:

  • (Message)

    when the command finishes.

Returns:

  • (Message, Object)

    message if no block was given, the return value of the block otherwise.

Raises:


101
102
103
104
105
106
107
108
# File 'lib/command/runner.rb', line 101

def pass!(interops = {}, options = {}, &block)
  options[:unsafe] = @unsafe
  env = options.delete(:env) || {}
  backend.call(*contents(interops), env, options, &block)

rescue Errno::ENOENT
  raise NoCommandError, @command
end