lib/core/transports.rb in buildr-1.2.0 vs lib/core/transports.rb in buildr-1.2.1
- old
+ new
@@ -54,11 +54,10 @@
# end
# Shorter version:
# File.open("image.jpg", "w") { |file| file.write URI.read("http://example.com/image.jpg") }
#
# Supported options:
- # * :proxy -- Collection of proxy settings, accessed by scheme.
# * :modified -- Only download if file modified since this timestamp. Returns nil if not modified.
# * :progress -- Show the progress bar while reading.
def read(uri, options = nil, &block)
uri = URI.parse(uri.to_s) unless URI === uri
uri.read options, &block
@@ -92,11 +91,10 @@
# end
# Or:
# write "sftp://localhost/jars/killer-app.jar", File.read("killer-app.jar")
#
# Supported options:
- # * :proxy -- Collection of proxy settings, accessed by scheme.
# * :progress -- Show the progress bar while reading.
def write(uri, *args, &block)
uri = URI.parse(uri.to_s) unless URI === uri
uri.write *args, &block
end
@@ -174,11 +172,23 @@
# that responds to +read+ and optionally +size+. The second form writes the content by yielding to the
# block. Each yield should return up to the specified number of bytes, the last yield returns nil.
#
# For options, see URI::write.
def write(*args, &block)
- fail "This protocol doesn't support writing (yet, how about helping by implementing it?)"
+ options = args.pop if Hash === args.last
+ options ||= {}
+ if String === args.first
+ ios = StringIO.new(args.first, "r")
+ write(options.merge(:size=>args.first.size)) { |bytes| ios.read(bytes) }
+ elsif args.first.respond_to?(:read)
+ size = args.first.size rescue nil
+ write({:size=>size}.merge(options)) { |bytes| args.first.read(bytes) }
+ elsif args.empty? && block
+ write_internal options, &block
+ else
+ raise ArgumentError, "Either give me the content, or pass me a block, otherwise what would I upload?"
+ end
end
# :call-seq:
# upload(source, options?)
#
@@ -272,12 +282,30 @@
end
yield progress_bar
end
end
+ # :call-seq:
+ # proxy_uri() => URI?
+ #
+ # Returns the proxy server to use. Obtains the proxy from the relevant environment variable (e.g. HTTP_PROXY).
+ # Supports exclusions based on host name and port number from environment variable NO_PROXY.
+ def proxy_uri()
+ proxy = ENV["#{scheme.upcase}_PROXY"]
+ proxy = URI.parse(proxy) if String === proxy
+ excludes = (ENV["NO_PROXY"] || "").split(/\s*,\s*/).compact
+ excludes = excludes.map { |exclude| exclude =~ /:\d+$/ ? exclude : "#{exclude}:*" }
+ return proxy unless excludes.any? { |exclude| File.fnmatch(exclude, "#{host}:#{port}") }
+ end
+
+ def write_internal(options, &block) #:nodoc:
+ fail "This protocol doesn't support writing (yet, how about helping by implementing it?)"
+ end
+
end
+
class HTTP #:nodoc:
# See URI::Generic#read
def read(options = nil, &block)
options ||= {}
@@ -320,90 +348,78 @@
raise RuntimeError, "Failed to download #{self}: #{response.message}"
end
end
end
- proxy = options[:proxy] && options[:proxy].http
- if proxy
+ if proxy = proxy_uri
proxy = URI.parse(proxy) if String === proxy
Net::HTTP.start(host, port, proxy.host, proxy.port, proxy.user, proxy.password) { |http| request[http] }
else
Net::HTTP.start(host, port) { |http| request[http] }
end
result
end
end
+
class SFTP #:nodoc:
class << self
# Caching of passwords, so we only need to ask once.
def passwords()
@passwords ||= {}
end
end
- # See URI::Generic#write
- def write(*args, &block)
- options = args.pop if Hash === args.last
- options ||= {}
- if String === args.first
- ios = StringIO.new(args.first, "r")
- write(options.merge(:size=>args.first.size)) { |bytes| ios.read(bytes) }
- elsif args.first.respond_to?(:read)
- size = args.first.size rescue nil
- write({:size=>size}.merge(options)) { |bytes| args.first.read(bytes) }
- elsif args.empty? && block
+ protected
- # SSH options are based on the username/password from the URI.
- ssh_options = { :port=>port, :username=>user }.merge(options[:ssh_options] || {})
- ssh_options[:password] ||= SFTP.passwords[host]
- begin
- puts "Connecting to #{host}" if Rake.application.options.trace
- session = Net::SSH.start(host, ssh_options)
- SFTP.passwords[host] = ssh_options[:password]
- rescue Net::SSH::AuthenticationFailed=>ex
- # Only if running with console, prompt for password.
- if !ssh_options[:password] && $stdout.isatty
- password = HighLine.new.ask("Password for #{host}:") { |q| q.echo = "*" }
- ssh_options[:password] = password
- retry
- end
- raise
+ def write_internal(options, &block) #:nodoc:
+ # SSH options are based on the username/password from the URI.
+ ssh_options = { :port=>port, :username=>user }.merge(options[:ssh_options] || {})
+ ssh_options[:password] ||= SFTP.passwords[host]
+ begin
+ puts "Connecting to #{host}" if Rake.application.options.trace
+ session = Net::SSH.start(host, ssh_options)
+ SFTP.passwords[host] = ssh_options[:password]
+ rescue Net::SSH::AuthenticationFailed=>ex
+ # Only if running with console, prompt for password.
+ if !ssh_options[:password] && $stdout.isatty
+ password = HighLine.new.ask("Password for #{host}:") { |q| q.echo = "*" }
+ ssh_options[:password] = password
+ retry
end
+ raise
+ end
- session.sftp.connect do |sftp|
- puts "connected" if Rake.application.options.trace
+ session.sftp.connect do |sftp|
+ puts "connected" if Rake.application.options.trace
- # To create a path, we need to create all its parent. We use realpath to determine if
- # the path already exists, otherwise mkdir fails.
- puts "Creating path #{@base_path}" if Rake.application.options.trace
- path.split("/").inject("") do |base, part|
- combined = base + part
- sftp.realpath combined rescue sftp.mkdir combined, {}
- "#{combined}/"
- end
+ # To create a path, we need to create all its parent. We use realpath to determine if
+ # the path already exists, otherwise mkdir fails.
+ puts "Creating path #{@base_path}" if Rake.application.options.trace
+ path.split("/").inject("") do |base, part|
+ combined = base + part
+ sftp.realpath combined rescue sftp.mkdir combined, {}
+ "#{combined}/"
+ end
- with_progress_bar options[:progress] && options[:size], path.split("/"), options[:size] || 0 do |progress|
- puts "Uploading to #{path}" if Rake.application.options.trace
- sftp.open_handle(path, "w") do |handle|
- # Writing in chunks gives us the benefit of a progress bar,
- # but also require that we maintain a position in the file,
- # since write() with two arguments always writes at position 0.
- pos = 0
- while chunk = yield(32 * 4096)
- sftp.write(handle, chunk, pos)
- pos += chunk.size
- progress << chunk
- end
- sftp.setstat(target_path, :permissions => options[:permissions]) if options[:permissions]
+ with_progress_bar options[:progress] && options[:size], path.split("/"), options[:size] || 0 do |progress|
+ puts "Uploading to #{path}" if Rake.application.options.trace
+ sftp.open_handle(path, "w") do |handle|
+ # Writing in chunks gives us the benefit of a progress bar,
+ # but also require that we maintain a position in the file,
+ # since write() with two arguments always writes at position 0.
+ pos = 0
+ while chunk = yield(32 * 4096)
+ sftp.write(handle, chunk, pos)
+ pos += chunk.size
+ progress << chunk
end
+ sftp.setstat(path, :permissions => options[:permissions]) if options[:permissions]
end
end
- else
- raise ArgumentError, "Either give me the content, or pass me a block, otherwise what would I upload?"
end
end
end
@@ -450,50 +466,38 @@
block ? block.call(input.read) : input.read
end
end
end
- # See URI::Generic#write
- def write(*args, &block)
- options = args.pop if Hash === args.last
- options ||= {}
- raise ArgumentError, "Either you're attempting to write a file to another host (which we don't support), or you used two slashes by mistake, where you should have file:///<path>." unless host.blank?
-
- if String === args.first
- ios = StringIO.new(args.first, "r")
- write(options.merge(:size=>args.first.size)) { |bytes| ios.read(bytes) }
- elsif args.first.respond_to?(:read)
- size = args.first.size rescue nil
- write({:size=>size}.merge(options)) { |bytes| args.first.read(bytes) }
- elsif args.empty? && block
- temp = nil
- Tempfile.open File.basename(path) do |temp|
- temp.binmode
- with_progress_bar options[:progress] && options[:size], path.split("/"), options[:size] || 0 do |progress|
- while chunk = yield(32 * 4096)
- temp.write chunk
- progress << chunk
- end
- end
- end
- real_path.tap do |path|
- mkpath File.dirname(path)
- File.move temp.path, path
- end
- else
- raise ArgumentError, "Either give me the content, or pass me a block, otherwise what would I upload?"
- end
- end
-
def to_s()
"file://#{host}#{path}"
end
# The URL path always starts with a backslash. On most operating systems (Linux, Darwin, BSD) it points
# to the absolute path on the file system. But on Windows, it comes before the drive letter, creating an
# unusable path, so real_path fixes that. Ugly but necessary hack.
def real_path() #:nodoc:
RUBY_PLATFORM =~ /win32/ && path =~ /^\/[a-zA-Z]:\// ? path[1..-1] : path
+ end
+
+ protected
+
+ def write_internal(options, &block) #:nodoc:
+ raise ArgumentError, "Either you're attempting to write a file to another host (which we don't support), or you used two slashes by mistake, where you should have file:///<path>." unless host.blank?
+ temp = nil
+ Tempfile.open File.basename(path) do |temp|
+ temp.binmode
+ with_progress_bar options[:progress] && options[:size], path.split("/"), options[:size] || 0 do |progress|
+ while chunk = yield(32 * 4096)
+ temp.write chunk
+ progress << chunk
+ end
+ end
+ end
+ real_path.tap do |path|
+ mkpath File.dirname(path)
+ File.move temp.path, path
+ end
end
@@schemes["FILE"] = FILE
end