class Kanrisuru::Remote::File

Constants

READ_FILE_SIZE
WRITE_LINE_COUNT

Attributes

blocks[R]
chars[R]
gid[R]
group[R]
inode[R]
last_access[R]
last_changed[R]
last_modified[R]
lines[R]
mode[R]
path[R]
size[R]
type[R]
uid[R]
user[R]
words[R]

Public Class Methods

new(path, host, backup = nil) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 16
def initialize(path, host, backup = nil)
  @path = path
  @host = host
  @backup = backup

  @file_lines = []

  reload! if exists?
end

Public Instance Methods

[](index) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 41
def [](index)
  if chunk_read_file? && index < @lines
    chunk_read_line_by_index(index)
  elsif index < @lines
    @file_lines[index]
  else
    raise ArgumentError, "Out of bounds index access for #{index}"
  end
end
append(&block) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 159
def append(&block)
  return unless writeable?

  new_lines = []
  block.call(new_lines)

  backup_file if should_backup?
  write_lines_to_file(new_lines, 'append')
end
chmod(mode) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 59
def chmod(mode)
  result = @host.chmod(@path, mode)
  update_file_attributes(result) if result.success?
end
chown(owner, group) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 64
def chown(owner, group)
  result = @host.chown(@path, owner: owner, group: group)
  update_file_attributes(result) if result.success?
end
delete() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 202
def delete
  result = @host.unlink(@path)

  init_file_attirbutes if result.success?

  result.success?
end
dir?() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 51
def dir?
  @host.dir?(@path)
end
each(&block) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 210
def each(&block)
  if chunk_read_file?
    each_chunk(&block)
  else
    @file_lines.each { |line| block.call(line) }
  end
end
exists?() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 33
def exists?
  @host.inode?(@path)
end
expand_path() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 26
def expand_path
  return '' unless exists?

  result = @host.realpath(@path)
  result.success? ?       result.path : ''
end
file?() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 37
def file?
  @host.file?(@path)
end
find_and_append(regex, new_line) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 117
def find_and_append(regex, new_line)
  new_lines = []

  each do |existing_line|
    new_lines << existing_line
    new_lines << new_line if regex.match(existing_line)
  end

  write_lines_to_file(new_lines, 'write')
end
find_and_prepend(regex, new_line) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 128
def find_and_prepend(regex, new_line)
  new_lines = []

  each do |existing_line|
    new_lines << new_line if regex.match(existing_line)
    new_lines << existing_line
  end

  write_lines_to_file(new_lines, 'write')
end
find_and_remove(regex) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 139
def find_and_remove(regex)
  new_lines = []

  each do |existing_line|
    new_lines << existing_line unless regex.match(existing_line)
  end

  write_lines_to_file(new_lines, 'write')
end
find_and_replace_line(regex, new_line) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 103
def find_and_replace_line(regex, new_line)
  new_lines = []

  each do |existing_line|
    new_lines << if regex.match(existing_line)
                   new_line
                 else
                   existing_line
                 end
  end

  write_lines_to_file(new_lines, 'write')
end
find_and_replace_value(regex, value) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 89
def find_and_replace_value(regex, value)
  new_lines = []

  each do |existing_line|
    new_lines << if regex.match(existing_line)
                   existing_line.gsub(regex, value)
                 else
                   existing_line
                 end
  end

  write_lines_to_file(new_lines, 'write')
end
prepend(&block) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 169
def prepend(&block)
  return unless writeable?

  new_lines = []
  block.call(new_lines)

  backup_file if should_backup?

  ## If large file, use tmp file to prepend to
  if chunk_read_file?
    tmp_file = "/tmp/kanrisuru-tempfile-#{Time.now.strftime('%Y-%m-%d-%H-%M-%S-%L')}"

    @host.echo(new_lines.join('\\n'), new_file: tmp_file, backslash: true, mode: 'write')
    @host.cat(@path, new_file: tmp_file, mode: 'append')
    @host.cp(tmp_file, @path)

    @host.rm(tmp_file)
    reload!
  else
    all_lines = new_lines + @file_lines
    write_lines_to_file(all_lines, 'write')
  end
end
reload!() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 218
def reload!
  @writeable = nil
  @file_lines = []

  wc_file
  stat_file
  read
end
rename(new_path) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 193
def rename(new_path)
  # @host.mv()
end
touch() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 197
def touch
  result = @host.touch(@path)
  update_file_attributes(result[0]) if result.success?
end
write(&block) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 149
def write(&block)
  return unless writeable?

  new_lines = []
  block.call(new_lines)

  backup_file if should_backup?
  write_lines_to_file(new_lines, 'write')
end
writeable?() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 69
def writeable?
  return @writeable if [true, false].include?(@writeable)

  if !file? && !zero?
    @writeable = false
    return false
  end

  current_user = @host.remote_user
  result = @host.get_user(current_user)

  raise 'Invalid result' unless result.success?

  groups = result.groups.map(&:name)

  @writeable = @mode.other.write? ||
               (@mode.group.write? && groups.include?(@group)) ||
               (@mode.owner.write? && @user == current_user)
end
zero?() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 55
def zero?
  @host.empty_file?(@path)
end

Private Instance Methods

backup_file() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 233
def backup_file
  result = @host.cp(@path, @backup)
  raise "Backup of #{@path} failed" if result.failure?
end
chunk_read_file?() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 293
def chunk_read_file?
  @size >= READ_FILE_SIZE
end
chunk_read_line_by_index(index) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 297
def chunk_read_line_by_index(index)
  result = @host.read_file_chunk(@path, index + 1, index + 1)
  result.success? ? result[0] : nil
end
chunk_write_to_file(lines, mode) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 278
def chunk_write_to_file(lines, mode)
  ## Clear initial file to write new data
  if mode == 'write'
    @host.unlink(@path)
    @host.touch(@path)
  end

  lines.each_slice(WRITE_LINE_COUNT) do |lines_slice|
    result = @host.echo(lines_slice.join('\\n'), new_file: @path, backslash: true, mode: 'append')
    raise 'Error appending lines to file' if result.failure?
  end

  reload!
end
each_chunk(&block) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 238
def each_chunk(&block)
  chunk_size = @lines >> 1
  index = 1

  loop do
    result = @host.read_file_chunk(@path, index, index + chunk_size - 1)
    break if result.failure?

    lines = result.data
    lines.each { |line| block.call(line) }

    break if index >= @lines

    index += chunk_size
  end
end
init_file_attirbutes() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 333
def init_file_attirbutes
  @writeable = nil
  @mode = nil
  @blocks = nil
  @size = nil
  @type = nil
  @gid = nil
  @group = nil
  @uid = nil
  @user = nil
  @inode = nil
  @last_access = nil
  @last_modified = nil
  @last_changed = nil

  @lines = nil
  @words = nil
  @chars = nil
end
read() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 255
def read
  return if chunk_read_file?

  result = @host.cat(@path)
  raise 'Error reading remote file' if result.failure?

  @file_lines = result.data
end
should_backup?() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 229
def should_backup?
  Kanrisuru::Util.present?(@backup)
end
stat_file() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 312
def stat_file
  result = @host.stat(@path)

  update_file_attributes(result) if result.success?
end
update_file_attributes(result) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 318
def update_file_attributes(result)
  @mode = result.mode
  @blocks = result.blocks
  @size = result.fsize
  @type = result.file_type
  @gid = result.gid
  @group = result.group
  @uid = result.uid
  @user = result.user
  @inode = result.inode
  @last_access = result.last_access
  @last_modified = result.last_modified
  @last_changed = result.last_changed
end
wc_file() click to toggle source
# File lib/kanrisuru/remote/file.rb, line 302
def wc_file
  result = @host.wc(@path)

  return if result.failure?

  @lines = result.lines
  @words = result.words
  @chars = result.characters
end
write_lines_to_file(lines, mode) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 264
def write_lines_to_file(lines, mode)
  if lines.length < WRITE_LINE_COUNT
    write_to_file(lines, mode)
  else
    chunk_write_to_file(lines, mode)
  end
end
write_to_file(lines, mode) click to toggle source
# File lib/kanrisuru/remote/file.rb, line 272
def write_to_file(lines, mode)
  result = @host.echo(lines.join('\\n'), new_file: @path, backslash: true, mode: mode)

  reload! if result.success?
end