Module: Cocov::PluginKit::Exec
- Defined in:
- lib/cocov/plugin_kit/exec.rb
Overview
Exec provides utilities for executing processes and obtaining its results.
Defined Under Namespace
Classes: ExecutionError
Class Method Summary collapse
-
.exec(cmd, **options) ⇒ Object
Public: exec works exactly like #exec2, but only returns the stdout stream, instead of both stdout and stderr.
-
.exec2(cmd, **options) ⇒ Object
Public: Executes a given command (represented as an array of strings), returning both its stdout and stderr streams as Strings.
Class Method Details
.exec(cmd, **options) ⇒ Object
Public: exec works exactly like #exec2, but only returns the stdout stream, instead of both stdout and stderr. For more information, see the documentation for #exec.
90 91 92 |
# File 'lib/cocov/plugin_kit/exec.rb', line 90 def exec(cmd, **) exec2(cmd, **).first end |
.exec2(cmd, **options) ⇒ Object
Public: Executes a given command (represented as an array of strings), returning both its stdout and stderr streams as Strings. Extra options are passed directly to Process.spawn, except:
-
env: when provided must be a Hash representing environment
keys and values. -
isolate_env: Prevents the current ENV from being copied into the new
process. Just a fancier name to :unsetenv_others
This function will block until the process finishes, either returning both streams (stdout, stderr) as an Array, or raising an ExecutionError.
Example:
stdout, stderr = Exec::exec2(["git", "version"], chdir: "/tmp")
# stdout == "git version 2.30.2\n"
# stderr == ""
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/cocov/plugin_kit/exec.rb', line 42 def exec2(cmd, **) out_reader, out_writer = IO.pipe err_reader, err_writer = IO.pipe isolate = .delete(:isolate_env) == true env = (.delete(:env) || {}).to_h { |*a| a.map(&:to_s) } .delete(:chdir) if .fetch(:chdir, nil).nil? opts = { unsetenv_others: isolate, out: out_writer.fileno, err: err_writer.fileno }.merge pid = Process.spawn(env, cmd, **opts) mut = Mutex.new cond = ConditionVariable.new status = nil Thread.new do _pid, status = Process.wait2(pid) mut.synchronize { cond.signal } end out_writer.close err_writer.close stdout = nil stderr = nil out_thread = Thread.new { stdout = out_reader.read } err_thread = Thread.new { stderr = err_reader.read } mut.synchronize { cond.wait(mut, 0.1) } while status.nil? out_thread.join err_thread.join out_reader.close err_writer.close err_reader.close raise ExecutionError.new(status.exitstatus, stdout, stderr, cmd, env) unless status.success? [stdout, stderr] end |