1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
require "pathname"
module VagrantPlugins
module FTPPush
class Adapter
attr_reader :host
attr_reader :port
attr_reader :username
attr_reader :password
attr_reader :options
attr_reader :server
def initialize(host, username, password, options = {})
@host, @port = parse_host(host)
@username = username
@password = password
@options = options
@server = nil
end
# Parse the host into it's url and port parts.
# @return [Array]
def parse_host(host)
if host.include?(":")
split = host.split(":", 2)
[split[0], split[1].to_i]
else
[host, default_port]
end
end
def default_port
raise NotImplementedError
end
def connect(&block)
raise NotImplementedError
end
def upload(local, remote)
raise NotImplementedError
end
end
#
# The FTP Adapter
#
class FTPAdapter < Adapter
def initialize(*)
require "net/ftp"
super
end
def default_port
21
end
def connect(&block)
@server = Net::FTP.new
@server.passive = options.fetch(:passive, true)
@server.connect(host, port)
@server.login(username, password)
begin
yield self
ensure
@server.close
end
end
def upload(local, remote)
parent = File.dirname(remote)
fullpath = Pathname.new(File.expand_path(parent, pwd))
# Create the parent directories if they does not exist (naive mkdir -p)
fullpath.descend do |path|
if !directory_exists?(path.to_s)
@server.mkdir(path.to_s)
end
end
# Upload the file
@server.putbinaryfile(local, remote)
end
def directory_exists?(path)
begin
@server.chdir(path)
return true
rescue Net::FTPPermError
return false
end
end
private
def pwd
@pwd ||= @server.pwd
end
end
#
# The SFTP Adapter
#
class SFTPAdapter < Adapter
def initialize(*)
require "net/sftp"
super
@dirs = {}
end
def default_port
22
end
def connect(&block)
Net::SFTP.start(@host, @username, password: @password, port: @port) do |server|
@server = server
yield self
end
end
def upload(local, remote)
dir = File.dirname(remote)
fullpath = Pathname.new(dir)
fullpath.descend do |path|
if @dirs[path.to_s].nil?
begin
@server.mkdir!(path.to_s)
# Cache visited directories in a list to avoid duplicate requests
@dirs[path.to_s] = true
rescue Net::SFTP::StatusException => e
# Directory exists, skip...
end
end
end
@server.upload!(local, remote)
end
end
end
end
|