class RemoteMarshal

Constants

VERSION

Public Class Methods

new(host, user, options) click to toggle source
# File lib/remote_marshal.rb, line 7
def initialize(host, user, options)
  @ssh = create_ssh(host, user, options)
end

Public Instance Methods

eval(&block) click to toggle source
# File lib/remote_marshal.rb, line 11
def eval(&block)
  command = block.to_source(strip_enclosure: true)

  call { |dir| marshal(StringIO.new(command), File.join(dir, token)) }
end
exec!(command) click to toggle source
# File lib/remote_marshal.rb, line 21
def exec!(command)
  status, output, error = nil, [], []

  @ssh.call do |ssh|
    channel = ssh.open_channel do |chan|
      chan.exec command do |ch, success|
        raise command unless success

        ch.on_data                   { |_, data|    output << data }
        ch.on_extended_data          { |_, _, data| error  << data }
        ch.on_request('exit-status') { |_, data|    status =  data.read_long }
      end
    end

    channel.wait
  end

  [status] + [output, error].map(&:join)
end
file(filename) click to toggle source
# File lib/remote_marshal.rb, line 17
def file(filename)
  call { |dir| marshal(filename, File.join(dir, File.basename(filename))) }
end
test?(name, option = nil) click to toggle source
# File lib/remote_marshal.rb, line 47
def test?(name, option = nil)
  exec!(%([ #{option} #{name} ]))
end

Private Instance Methods

call(&block) click to toggle source
# File lib/remote_marshal.rb, line 53
def call(&block)
  status, output, error = mktmpdir

  return [status, output, error] unless status == 0

  dir                   = output.chomp
  ret                   = block.(dir)
  status, output, error = remove_entry_secure(dir)

  return [status, output, error] unless status == 0

  status, output, error = *ret

  return [status, output, error] unless status == 0

  [status, Marshal.load(output.chomp), error]
end
create_ssh(host, user, options) click to toggle source
# File lib/remote_marshal.rb, line 91
def create_ssh(host, user, options)
  lambda do |&block|
    Net::SSH.start(host, user, options) do |ssh|
      block.(ssh)

      ssh.loop
    end
  end
end
marshal(src, dst) click to toggle source
# File lib/remote_marshal.rb, line 85
def marshal(src, dst)
  upload!(src, dst)

  exec!("ruby -e 'puts Marshal.dump(eval(open(ARGV[0], &:read)))' #{dst}")
end
mktmpdir() click to toggle source
# File lib/remote_marshal.rb, line 71
def mktmpdir
  exec!("ruby -r tmpdir -e 'puts Dir.mktmpdir'")
end
remove_entry_secure(dir) click to toggle source
# File lib/remote_marshal.rb, line 75
def remove_entry_secure(dir)
  exec!(%(ruby -r fileutils -e "FileUtils.remove_entry_secure '#{dir}'"))
end
token() click to toggle source
# File lib/remote_marshal.rb, line 79
def token
  seed = ([Time.now] + (1..10).map { rand.to_s }).join('--')

  Digest::SHA1.hexdigest(seed)
end