Class: Yobi::ResticOutput

Inherits:
Object
  • Object
show all
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.

Returns:

  • (Integer)
4096

Instance Method Summary collapse

Constructor Details

#initialize(file, tail_chunk_size: DEFAULT_TAIL_CHUNK_SIZE) ⇒ ResticOutput

Returns a new instance of ResticOutput.

Parameters:

  • file (File)
  • tail_chunk_size (Integer) (defaults to: DEFAULT_TAIL_CHUNK_SIZE)

    read window size for #last_line

  • tail_chunk_size: (Integer) (defaults to: DEFAULT_TAIL_CHUNK_SIZE)


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_linevoid #each_lineEnumerator[String, void]

Returns if no block is given.

Overloads:

  • #each_linevoid

    This method returns an undefined value.

  • #each_lineEnumerator[String, void]

    Returns:

    • (Enumerator[String, void])

Yields:

Yield Parameters:

  • line (String)

Yield Returns:

  • (void)

Returns:

  • (Enumerator)

    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

#indexHash{String => Array<Integer>}

Byte offsets of every line, grouped by message_type. Built once and memoized.

Returns:

  • (Hash{String => Array<Integer>})


29
30
31
# File 'lib/yobi/restic_output.rb', line 29

def index
  @index ||= build_index
end

#last_lineString?

The last non-blank line, found by seeking backward from the end of the file.

Returns:

  • (String, nil)


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.

Parameters:

  • offset (Integer)

    a byte offset, as recorded by #index

Returns:

  • (String)

    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_sString

Returns the full captured output.

Returns:

  • (String)

    the full captured output



73
74
75
76
# File 'lib/yobi/restic_output.rb', line 73

def to_s
  @file.rewind
  @file.read
end