Class: Hanami::CLI::SystemCall

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

Overview

Facility for making convenient system calls and returning their results.

Since:

  • 2.0.0

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Instance Method Details

#call(cmd, env: {}) ⇒ Result #call(cmd, env: {}, &blk) ⇒ Result

Executes the given system command and returns the result.

Overloads:

  • #call(cmd, env: {}, &blk) ⇒ Result

    Executes the command and passes the given block to the Open3.popen3 method called internally.

    Examples:

    call("info") do |stdin, stdout, stderr, wait_thread|
      # ...
    end
    

Since:

  • 2.0.0



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/hanami/cli/system_call.rb', line 88

def call(cmd, *args, env: {})
  exit_code = nil
  out = nil
  err = nil

  ::Bundler.with_original_env do
    Open3.popen3(env, command(cmd, *args)) do |stdin, stdout, stderr, wait_thr|
      yield stdin, stdout, stderr, wait_thr if block_given?

      stdin.close

      # Read output before waiting on the process, to prevent deadlock. If we wait on the
      # process first, and the process writes enough data to fill the limited OS pipe buffers,
      # then the process will block waiting for us to read, while _we're_ blocked waiting for
      # it to finish. Reading first allows us to drain the buffers as output arrives.
      out = Thread.new { stdout.read }.value.strip
      err = Thread.new { stderr.read }.value.strip
      exit_code = wait_thr&.value&.exitstatus
    end
  end

  Result.new(exit_code:, out:, err:)
end

#command(cmd, *args) ⇒ Object

Since:

  • 2.1.0



114
115
116
# File 'lib/hanami/cli/system_call.rb', line 114

def command(cmd, *args)
  [cmd, args].flatten(1).compact.join(" ")
end