lib/io_streams/paths/sftp.rb in iostreams-1.0.0.beta7 vs lib/io_streams/paths/sftp.rb in iostreams-1.0.0

- old
+ new

@@ -1,9 +1,29 @@ require 'open3' module IOStreams module Paths + # Read a file from a remote sftp server. + # + # Example: + # IOStreams. + # path("sftp://example.org/path/file.txt", username: "jbloggs", password: "secret", compression: false). + # reader do |input| + # puts input.read + # end + # + # Note: + # - raises Net::SFTP::StatusException when the file could not be read. + # + # Write to a file on a remote sftp server. + # + # Example: + # IOStreams. + # path("sftp://example.org/path/file.txt", username: "jbloggs", password: "secret", compression: false). + # writer do |output| + # output.write('Hello World') + # end class SFTP < IOStreams::Path include SemanticLogger::Loggable if defined?(SemanticLogger) class << self attr_accessor :sshpass_bin, :sftp_bin, :sshpass_wait_seconds @@ -52,11 +72,11 @@ # # # When using the sftp executable use an identity file instead of a password to authenticate: # IOStreams.path("sftp://test.com/path/file_name.csv", username: "jack", IdentityFile: "~/.ssh/private_key").reader do |io| # puts io.read # end - def initialize(url, username: nil, password: nil, ruby: true, ssh_options: {}) + def initialize(url, username: nil, password: nil, ssh_options: {}) uri = Utils::URI.new(url) raise(ArgumentError, "Invalid URL. Required Format: 'sftp://<host_name>/<file_name>'") unless uri.scheme == 'sftp' @hostname = uri.hostname @mkdir = false @@ -85,44 +105,10 @@ def mkdir @mkdir = true self end - # Read a file from a remote sftp server. - # - # Example: - # IOStreams. - # path("sftp://example.org/path/file.txt", username: "jbloggs", password: "secret", compression: false). - # reader do |input| - # puts input.read - # end - # - # Note: - # - raises Net::SFTP::StatusException when the file could not be read. - def reader(&block) - IOStreams.temp_file("iostreams-sftp-reader") do |temp_file| - sftp_download(path, temp_file.to_s) - ::File.open(temp_file.to_s, "rb") { |io| streams.reader(io, &block) } - end - end - - # Write to a file on a remote sftp server. - # - # Example: - # IOStreams. - # path("sftp://example.org/path/file.txt", username: "jbloggs", password: "secret", compression: false). - # writer do |output| - # output.write('Hello World') - # end - def writer(&block) - IOStreams.temp_file("iostreams-sftp-writer") do |temp_file| - ::File.open(temp_file.to_s, "wb") { |io| streams.writer(io, &block) } - sftp_upload(temp_file.to_s, path) - temp_file.size - end - end - # TODO: Add #copy_from shortcut to detect when a file is supplied that does not require conversion. # Search for files on the remote sftp server that match the provided pattern. # # The pattern matching works like Net::SFTP::Operations::Dir.glob and Dir.glob @@ -145,19 +131,34 @@ flags |= ::File::FNM_DOTMATCH if hidden Net::SFTP.start(hostname, username, build_ssh_options) do |sftp| sftp.dir.glob(".", pattern, flags) do |path| next if !directories && !path.file? - new_path = self.class.new("sftp://#{hostname}/#{path.name}", username: username, password: password, ruby: ruby, **ssh_options) + new_path = self.class.new("sftp://#{hostname}/#{path.name}", username: username, password: password, **ssh_options) yield(new_path, path.attributes.attributes) end end nil end private attr_reader :password + + def stream_reader(&block) + IOStreams.temp_file("iostreams-sftp-reader") do |temp_file| + sftp_download(path, temp_file.to_s) + ::File.open(temp_file.to_s, "rb") { |io| builder.reader(io, &block) } + end + end + + def stream_writer(&block) + IOStreams.temp_file("iostreams-sftp-writer") do |temp_file| + ::File.open(temp_file.to_s, "wb") { |io| builder.writer(io, &block) } + sftp_upload(temp_file.to_s, path) + temp_file.size + end + end # Use sftp and sshpass executables to download to a local file def sftp_download(remote_file_name, local_file_name) with_sftp_args do |args| Open3.popen2e(*args) do |writer, reader, waith_thr|