Class: Yobi::ResticOutput
- Inherits:
-
Object
- Object
- Yobi::ResticOutput
- Defined in:
- lib/yobi/restic_output.rb,
sig/yobi.rbs
Overview
Wraps the tempfile a repository operation's stdout+stderr are both written to, with random access so a caller asking only for the last line (see #last_line) doesn't have to read the entire output.
Constant Summary collapse
- DEFAULT_TAIL_CHUNK_SIZE =
Default read window size, in bytes, for #last_line.
4096
Instance Method Summary collapse
-
#each_line {|line| ... } ⇒ Enumerator
If no block is given.
-
#index ⇒ Hash{String => Array<Integer>}
Byte offsets of every line, grouped by message_type.
-
#initialize(file, tail_chunk_size: DEFAULT_TAIL_CHUNK_SIZE) ⇒ ResticOutput
constructor
A new instance of ResticOutput.
-
#last_line ⇒ String?
The last non-blank line, found by seeking backward from the end of the file.
-
#read_line_at(offset) ⇒ String
The line starting at that offset.
-
#to_s ⇒ String
The full captured output.
Constructor Details
#initialize(file, tail_chunk_size: DEFAULT_TAIL_CHUNK_SIZE) ⇒ ResticOutput
Returns a new instance of ResticOutput.
20 21 22 23 |
# File 'lib/yobi/restic_output.rb', line 20 def initialize(file, tail_chunk_size: DEFAULT_TAIL_CHUNK_SIZE) @file = file @tail_chunk_size = tail_chunk_size end |
Instance Method Details
#each_line ⇒ void #each_line ⇒ Enumerator[String, void]
Returns if no block is given.
65 66 67 68 69 70 |
# File 'lib/yobi/restic_output.rb', line 65 def each_line(&block) return enum_for(:each_line) unless block_given? @file.rewind @file.each_line(&block) end |
#index ⇒ Hash{String => Array<Integer>}
Byte offsets of every line, grouped by message_type. Built once and memoized.
29 30 31 |
# File 'lib/yobi/restic_output.rb', line 29 def index @index ||= build_index end |
#last_line ⇒ String?
The last non-blank line, found by seeking backward from the end of the file.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/yobi/restic_output.rb', line 44 def last_line size = @file.size return nil if size.zero? window = @tail_chunk_size loop do read_size = [window, size].min @file.seek(size - read_size) lines = @file.read(read_size).each_line.to_a lines.shift if read_size < size line = lines.reverse_each.find { |candidate| !candidate.strip.empty? } return line.strip if line return nil if read_size == size window *= 2 end end |
#read_line_at(offset) ⇒ String
Returns the line starting at that offset.
35 36 37 38 |
# File 'lib/yobi/restic_output.rb', line 35 def read_line_at(offset) @file.seek(offset) @file.gets end |
#to_s ⇒ String
Returns the full captured output.
73 74 75 76 |
# File 'lib/yobi/restic_output.rb', line 73 def to_s @file.rewind @file.read end |