lib/dandelion/adapter/sftp.rb
require 'pathname'
require 'dandelion/utils'
module Dandelion
module Adapter
class SFTP < Adapter::Base
include ::Dandelion::Utils
adapter 'sftp'
requires_gems 'net-sftp'
def initialize(config)
begin
require 'highline/import'
rescue LoadError
end
require 'net/sftp'
@config = config
@config.defaults(preserve_permissions: true)
@sftp = sftp_client
end
def read(file)
begin
@sftp.file.open(path(file), 'r') do |f|
f.gets
end
rescue Net::SFTP::StatusException => e
raise unless e.code == 2
nil
end
end
def write(file, data)
temp(file, data) do |temp|
begin
@sftp.upload!(temp, path(file))
rescue Net::SFTP::StatusException => e
raise unless e.code == 2
mkdir_p(File.dirname(path(file)))
@sftp.upload!(temp, path(file))
end
end
if @config[:preserve_permissions]
mode = get_mode(file)
@sftp.setstat!(path(file), permissions: mode) if mode
end
end
def delete(file)
begin
@sftp.remove!(path(file))
cleanup(File.dirname(path(file)))
rescue Net::SFTP::StatusException => e
raise unless e.code == 2
end
end
def symlink(file, target)
begin
@sftp.symlink!(target, path(file))
rescue Net::SFTP::StatusException => e
if e.code == 2
mkdir_p(File.dirname(path(file)))
else
@sftp.remove!(path(file))
end
@sftp.symlink!(target, path(file))
end
end
def to_s
"sftp://#{@config['username']}@#{@config['host']}/#{@config['path']}"
end
private
def sftp_client
options = {
password: @config['password'],
port: @config['port'] || Net::SSH::Transport::Session::DEFAULT_PORT,
}
Net::SFTP.start(@config['host'], @config['username'], options)
end
def get_mode(file)
stat = File.stat(file) if File.exists?(file)
stat.mode if stat
end
def cleanpath(path)
Pathname.new(path).cleanpath.to_s if path
end
def cleanup(dir)
unless cleanpath(dir) == cleanpath(@config['path']) or dir == File.dirname(dir)
if empty?(dir)
@sftp.rmdir!(dir)
cleanup(File.dirname(dir))
end
end
end
def empty?(dir)
@sftp.dir.entries(dir).delete_if do |file|
file.name == '.' or file.name == '..'
end.empty?
end
def mkdir_p(dir)
begin
@sftp.mkdir!(dir)
rescue Net::SFTP::StatusException => e
raise unless e.code == 2
mkdir_p(File.dirname(dir))
@sftp.mkdir!(dir)
end
end
def path(file)
if @config['path'] and !@config['path'].empty?
File.join(@config['path'], file)
else
file
end
end
end
end
end