Class: Executo::CLI

Inherits:
Object
  • Object
show all
Defined in:
lib/executo/cli.rb

Class Method Summary collapse

Class Method Details

.array_of_strings?(array) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
# File 'lib/executo/cli.rb', line 58

def array_of_strings?(array)
  array.is_a?(Array) && array.all? { |c| c.is_a?(String) }
end

.escaped_command(command, shell_escape: true) ⇒ Object



29
30
31
32
33
# File 'lib/executo/cli.rb', line 29

def escaped_command(command, shell_escape: true)
  return command.join unless shell_escape

  command.shelljoin
end

.read_stream(stream, callback) ⇒ Object



48
49
50
51
52
53
54
55
56
# File 'lib/executo/cli.rb', line 48

def read_stream(stream, callback)
  Thread.new do
    until (line = stream.gets).nil?
      callback.call(line)
    end
  rescue IOError
    # ignore
  end
end

.run(cmd, stdout:, stderr:, stdin_content: [], stdin_newlines: true, shell_escape: true) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/executo/cli.rb', line 9

def run(cmd, stdout:, stderr:, stdin_content: [], stdin_newlines: true, shell_escape: true)
  raise 'cmd must be an array of Strings.' unless array_of_strings?(cmd)
  raise 'stdout must be a Proc.' unless stdout.is_a?(Proc)
  raise 'stderr must be a Proc.' unless stderr.is_a?(Proc)
  raise 'stdin_content must be an Array of Strings.' unless array_of_strings?(stdin_content)

  computed_cmd = escaped_command(cmd, shell_escape: shell_escape)
  Executo.logger.debug "computed cmd: #{computed_cmd}"
  Open3.popen3(computed_cmd) do |stdin_stream, stdout_stream, stderr_stream, thread|
    threads = []
    threads << write_stream(stdin_stream, stdin_content, newlines: stdin_newlines)
    threads << read_stream(stdout_stream, stdout)
    threads << read_stream(stderr_stream, stderr)
    threads << thread

    threads.each(&:join)
    thread.value
  end
end

.write_stream(stream, content, newlines: true) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/executo/cli.rb', line 35

def write_stream(stream, content, newlines: true)
  Thread.new do
    content.each do |input_line|
      stream.write(input_line)
      stream.write("\n") if input_line[-1] != "\n" && newlines
    end
  rescue Errno::EPIPE
    nil
  ensure
    stream.close
  end
end