Class: KamalBackup::Command

Inherits:
Object
  • Object
show all
Defined in:
lib/kamal_backup/command.rb

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.outputObject

Returns the value of attribute output.



34
35
36
# File 'lib/kamal_backup/command.rb', line 34

def output
  @output
end

Class Method Details

.available?(name) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
48
49
# File 'lib/kamal_backup/command.rb', line 44

def available?(name)
  ENV.fetch('PATH', '').split(File::PATH_SEPARATOR).any? do |dir|
    path = File.join(dir, name)
    File.executable?(path) && !File.directory?(path)
  end
end

.capture(spec, redactor:, input: nil, log: true, log_output: true, tee_stdout: nil, tee_stderr: nil) ⇒ Object



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
# File 'lib/kamal_backup/command.rb', line 51

def capture(spec, redactor:, input: nil, log: true, log_output: true, tee_stdout: nil, tee_stderr: nil)
  output = log ? self.output : nil
  return capture_quietly(spec, input: input, redactor: redactor) unless output || tee_stdout || tee_stderr

  context = output&.command_start(spec, redactor: redactor)
  stdout, stderr, status = popen_capture(
    spec,
    input: input,
    redactor: redactor,
    output: output,
    context: context,
    log_output: log_output,
    tee_stdout: tee_stdout,
    tee_stderr: tee_stderr
  )
  output&.command_exit(context, status.exitstatus)
  result = CommandResult.new(stdout: stdout, stderr: stderr, status: status.exitstatus,
                             streamed: !(tee_stdout || tee_stderr).nil?)

  raise command_failure(spec, status.exitstatus, stdout, stderr, redactor) unless status.success?

  result
rescue Errno::ENOENT => e
  raise command_not_found(spec, e)
end

.capture_pty(spec, redactor:, tee_stdout: nil) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/kamal_backup/command.rb', line 77

def capture_pty(spec, redactor:, tee_stdout: nil)
  output = +''
  tee_buffer = +''
  result = nil

  PTY.spawn(spec.env, *spec.argv) do |reader, writer, pid|
    writer.close

    begin
      loop do
        chunk = reader.readpartial(16 * 1024)
        output << chunk
        tee_buffer = tee_stream(tee_stdout, redactor, tee_buffer, chunk) if tee_stdout
      end
    rescue EOFError, Errno::EIO
      flush_tee_stream(tee_stdout, redactor, tee_buffer) if tee_stdout
    ensure
      reader.close unless reader.closed?
    end

    _, status = Process.wait2(pid)
    result = CommandResult.new(stdout: output, stderr: '', status: status.exitstatus, streamed: !tee_stdout.nil?)

    raise command_failure(spec, status.exitstatus, output, output, redactor) unless status.success?
  end

  result
rescue Errno::ENOENT => e
  raise command_not_found(spec, e)
end

.collect_stream(io, command_output: output, context: nil, stream: :stdout, log_output: true, tee_io: nil, redactor: nil) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/kamal_backup/command.rb', line 108

def collect_stream(io, command_output: output, context: nil, stream: :stdout, log_output: true, tee_io: nil,
                   redactor: nil)
  captured_output = +''
  tee_buffer = +''

  loop do
    chunk = io.readpartial(16 * 1024)
    captured_output << chunk
    command_output&.command_output(context, stream, chunk, redactor: redactor) if log_output && context
    tee_buffer = tee_stream(tee_io, redactor, tee_buffer, chunk) if tee_io
  rescue EOFError
    flush_tee_stream(tee_io, redactor, tee_buffer) if tee_io
    break
  end

  captured_output
end

.with_output(output) ⇒ Object



36
37
38
39
40
41
42
# File 'lib/kamal_backup/command.rb', line 36

def with_output(output)
  previous_output = self.output
  self.output = output
  yield
ensure
  self.output = previous_output
end