Module: Dev::Kit::System

Defined in:
lib/dev/kit/system.rb

Constant Summary collapse

SUDO_PROMPT =
Dev::UI.fmt("{{info:(sudo)}} Password: ")

Class Method Summary collapse

Class Method Details

.capture2(*a, sudo: false, env: ENV) ⇒ Object

Execute a command in the user’s environment This is meant to be largely equivalent to backticks, only with the env passed in. Captures the results of the command without output to the console

#### Parameters

  • ‘*a`: A splat of arguments evaluated as a command. (e.g. `’rm’, folder` is equivalent to ‘rm #folder`)

  • ‘sudo`: If truthy, run this command with sudo. If String, pass to `sudo_reason`

  • ‘env`: process environment with which to execute this command

#### Returns

  • ‘output`: output (STDOUT) of the command execution

  • ‘status`: boolean success status of the command execution

#### Usage ‘out, stat = Dev::Kit::System.capture2(’ls’, ‘a_folder’)‘



46
47
48
# File 'lib/dev/kit/system.rb', line 46

def capture2(*a, sudo: false, env: ENV)
  delegate_open3(*a, sudo: sudo, env: env, method: :capture2)
end

.capture2e(*a, sudo: false, env: ENV) ⇒ Object

Execute a command in the user’s environment This is meant to be largely equivalent to backticks, only with the env passed in. Captures the results of the command without output to the console

#### Parameters

  • ‘*a`: A splat of arguments evaluated as a command. (e.g. `’rm’, folder` is equivalent to ‘rm #folder`)

  • ‘sudo`: If truthy, run this command with sudo. If String, pass to `sudo_reason`

  • ‘env`: process environment with which to execute this command

#### Returns

  • ‘output`: output (STDOUT merged with STDERR) of the command execution

  • ‘status`: boolean success status of the command execution

#### Usage ‘out_and_err, stat = Dev::Kit::System.capture2e(’ls’, ‘a_folder’)‘



66
67
68
# File 'lib/dev/kit/system.rb', line 66

def capture2e(*a, sudo: false, env: ENV)
  delegate_open3(*a, sudo: sudo, env: env, method: :capture2e)
end

.capture3(*a, sudo: false, env: ENV) ⇒ Object

Execute a command in the user’s environment This is meant to be largely equivalent to backticks, only with the env passed in. Captures the results of the command without output to the console

#### Parameters

  • ‘*a`: A splat of arguments evaluated as a command. (e.g. `’rm’, folder` is equivalent to ‘rm #folder`)

  • ‘sudo`: If truthy, run this command with sudo. If String, pass to `sudo_reason`

  • ‘env`: process environment with which to execute this command

#### Returns

  • ‘output`: STDOUT of the command execution

  • ‘error`: STDERR of the command execution

  • ‘status`: boolean success status of the command execution

#### Usage ‘out, err, stat = Dev::Kit::System.capture3(’ls’, ‘a_folder’)‘



87
88
89
# File 'lib/dev/kit/system.rb', line 87

def capture3(*a, sudo: false, env: ENV)
  delegate_open3(*a, sudo: sudo, env: env, method: :capture3)
end

.sudo_reason(msg) ⇒ Object

Ask for sudo access with a message explaning the need for it Will make subsequent commands capable of running with sudo for a period of time

#### Parameters

  • ‘msg`: A message telling the user why sudo is needed

#### Usage ‘ctx.sudo_reason(“We need to do a thing”)`



21
22
23
24
25
26
27
28
# File 'lib/dev/kit/system.rb', line 21

def sudo_reason(msg)
  # See if sudo has a cached password
  `env SUDO_ASKPASS=/usr/bin/false sudo -A true`
  return if $CHILD_STATUS.success?
  Dev::UI.with_frame_color(:blue) do
    puts(Dev::UI.fmt("{{i}} #{msg}"))
  end
end

.system(*a, sudo: false, env: ENV, **kwargs) ⇒ Object

Execute a command in the user’s environment Outputs result of the command without capturing it

#### Parameters

  • ‘*a`: A splat of arguments evaluated as a command. (e.g. `’rm’, folder` is equivalent to ‘rm #folder`)

  • ‘sudo`: If truthy, run this command with sudo. If String, pass to `sudo_reason`

  • ‘env`: process environment with which to execute this command

  • ‘**kwargs`: additional keyword arguments to pass to Process.spawn

#### Returns

  • ‘status`: boolean success status of the command execution

#### Usage ‘stat = Dev::Kit::System.system(’ls’, ‘a_folder’)‘



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/dev/kit/system.rb', line 106

def system(*a, sudo: false, env: ENV, **kwargs)
  a = apply_sudo(*a, sudo)

  out_r, out_w = IO.pipe
  err_r, err_w = IO.pipe
  in_stream = STDIN.closed? ? :close : STDIN
  pid = Process.spawn(env, *resolve_path(a, env), 0 => in_stream, :out => out_w, :err => err_w, **kwargs)
  out_w.close
  err_w.close

  handlers = if block_given?
    { out_r => ->(data) { yield(data.force_encoding(Encoding::UTF_8), '') },
      err_r => ->(data) { yield('', data.force_encoding(Encoding::UTF_8)) }, }
  else
    { out_r => ->(data) { STDOUT.write(data) },
      err_r => ->(data) { STDOUT.write(data) }, }
  end

  loop do
    ios = [err_r, out_r].reject(&:closed?)
    break if ios.empty?

    readers, = IO.select(ios)
    readers.each do |io|
      begin
        handlers[io].call(io.readpartial(4096))
      rescue IOError
        io.close
      end
    end
  end

  Process.wait(pid)
  $CHILD_STATUS
end