You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildr.apache.org by as...@apache.org on 2008/01/16 10:42:32 UTC

svn commit: r612398 - in /incubator/buildr/trunk: CHANGELOG lib/core/transports.rb spec/transport_spec.rb

Author: assaf
Date: Wed Jan 16 01:42:29 2008
New Revision: 612398

URL: http://svn.apache.org/viewvc?rev=612398&view=rev
Log:
BUILDR-7

Modified:
    incubator/buildr/trunk/CHANGELOG
    incubator/buildr/trunk/lib/core/transports.rb
    incubator/buildr/trunk/spec/transport_spec.rb

Modified: incubator/buildr/trunk/CHANGELOG
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/CHANGELOG?rev=612398&r1=612397&r2=612398&view=diff
==============================================================================
--- incubator/buildr/trunk/CHANGELOG (original)
+++ incubator/buildr/trunk/CHANGELOG Wed Jan 16 01:42:29 2008
@@ -20,6 +20,7 @@
 * Removed: All deprecated features since 1.1.  If you've seen warnings before, except the build to break.
 * Fixed: Artifact.pom resolves artifact without classifier, i.e org.testng:testng:jar:jdk15:5.1 uses org.testng:testng:pom:5.1 (Tommy).
 * Fixed: More patches towards JRuby support, courtesy of Vic Borja.
+* Fixed: Error when downloading a file from a server which answers with a response with no content length.
 
 1.2.10 (2007-11-26)
 * Changed: Resources sets permission on copied files to make them read/write-able.

Modified: incubator/buildr/trunk/lib/core/transports.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/core/transports.rb?rev=612398&r1=612397&r2=612398&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/core/transports.rb (original)
+++ incubator/buildr/trunk/lib/core/transports.rb Wed Jan 16 01:42:29 2008
@@ -1,16 +1,16 @@
-require "cgi"
-require "net/http"
-require "net/https"
-require "net/ssh"
-require "net/sftp"
-require "uri"
-require "uri/sftp"
-require "digest/md5"
-require "digest/sha1"
-require "facets/progressbar"
-require "highline"
-require "tempfile"
-require "uri/sftp"
+require 'cgi'
+require 'net/http'
+require 'net/https'
+require 'net/ssh'
+require 'net/sftp'
+require 'uri'
+require 'uri/sftp'
+require 'digest/md5'
+require 'digest/sha1'
+require 'facets/progressbar'
+require 'highline'
+require 'tempfile'
+require 'uri/sftp'
 
 
 # Monkeypatching: SFTP never defines the mkdir method on its session or the underlying
@@ -50,11 +50,11 @@
     # the second form yields to the block with each chunk of content (usually more than one).
     #
     # For example:
-    #   File.open "image.jpg", "w" do |file|
-    #     URI.read("http://example.com/image.jpg") { |chunk| file.write chunk }
+    #   File.open 'image.jpg', 'w' do |file|
+    #     URI.read('http://example.com/image.jpg') { |chunk| file.write chunk }
     #   end
     # Shorter version:
-    #   File.open("image.jpg", "w") { |file| file.write URI.read("http://example.com/image.jpg") }
+    #   File.open('image.jpg', 'w') { |file| file.write URI.read('http://example.com/image.jpg') }
     #
     # Supported options:
     # * :modified -- Only download if file modified since this timestamp. Returns nil if not modified.
@@ -87,11 +87,11 @@
     # block. Each yield should return up to the specified number of bytes, the last yield returns nil.
     #
     # For example:
-    #   File.open "killer-app.jar", "rb" do |file|
-    #     write("sftp://localhost/jars/killer-app.jar") { |chunk| file.read(chunk) }
+    #   File.open 'killer-app.jar', 'rb' do |file|
+    #     write('sftp://localhost/jars/killer-app.jar') { |chunk| file.read(chunk) }
     #   end
     # Or:
-    #   write "sftp://localhost/jars/killer-app.jar", File.read("killer-app.jar")
+    #   write 'sftp://localhost/jars/killer-app.jar', File.read('killer-app.jar')
     #
     # Supported options:
     # * :progress -- Show the progress bar while reading.
@@ -127,7 +127,7 @@
     #
     # For options, see URI::read.
     def read(options = nil, &block)
-      fail "This protocol doesn't support reading (yet, how about helping by implementing it?)"
+      fail 'This protocol doesn\'t support reading (yet, how about helping by implementing it?)'
     end
 
     # :call-seq:
@@ -159,7 +159,7 @@
         read({:progress=>verbose}.merge(options || {}).merge(:modified=>target.mtime)) { |chunk| target.write chunk }
         target.flush
       else
-        raise ArgumentError, "Expecting a target that is either a file name (string, task) or object that responds to write (file, pipe)." unless target.respond_to?(:write)
+        raise ArgumentError, 'Expecting a target that is either a file name (string, task) or object that responds to write (file, pipe).' unless target.respond_to?(:write)
         read({:progress=>verbose}.merge(options || {})) { |chunk| target.write chunk }
         target.flush
       end
@@ -178,7 +178,7 @@
       options = args.pop if Hash === args.last
       options ||= {}
       if String === args.first
-        ios = StringIO.new(args.first, "r")
+        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
@@ -186,7 +186,7 @@
       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?"
+        raise ArgumentError, 'Either give me the content, or pass me a block, otherwise what would I upload?'
       end
     end
 
@@ -204,14 +204,14 @@
       source = source.name if Rake::Task === source
       options ||= {}
       if String === source
-        raise NotFoundError, "No source file/directory to upload." unless File.exist?(source)
+        raise NotFoundError, 'No source file/directory to upload.' unless File.exist?(source)
         if File.directory?(source)
           Dir.glob("#{source}/**/*").reject { |file| File.directory?(file) }.each do |file|
-            uri = self + (File.join(self.path, file.sub(source, "")))
+            uri = self + (File.join(self.path, file.sub(source, '')))
             uri.upload file, {:digests=>[]}.merge(options)
           end
         else
-          File.open(source, "rb") { |input| upload input, options }
+          File.open(source, 'rb') { |input| upload input, options }
         end
       elsif source.respond_to?(:read)
         digests = (options[:digests] || [:md5, :sha1]).
@@ -227,7 +227,7 @@
             (options).merge(:progress=>false)
         end
       else
-        raise ArgumentError, "Expecting source to be a file name (string, task) or any object that responds to read (file, pipe)."
+        raise ArgumentError, 'Expecting source to be a file name (string, task) or any object that responds to read (file, pipe).'
       end
     end
 
@@ -245,7 +245,7 @@
     # The block is yielded with a progress object that implements a single method.
     # Call << for each block of bytes down/uploaded.
     def with_progress_bar(enable, file_name, size) #:nodoc:
-      if enable && $stdout.isatty
+      if enable && $stdout.isatty && size
         progress_bar = Console::ProgressBar.new(file_name, size)
         # Extend the progress bar so we can display count/total.
         class << progress_bar
@@ -255,15 +255,15 @@
         end
         # Squeeze the filename into 30 characters.
         if file_name.size > 30
-          base, ext = file_name.split(".")
+          base, ext = file_name.split('.')
           truncated = "#{base[0..26-ext.to_s.size]}...#{ext}"
         else
           truncated = file_name
         end
         progress_bar.format = "#{truncated}: %3d%% %s %s/%s %s"
-        progress_bar.format = "%3d%% %s %s/%s %s"
+        progress_bar.format = '%3d%% %s %s/%s %s'
         progress_bar.format_arguments = [:percentage, :bar, :bytes, :total, :stat]
-        progress_bar.bar_mark = "."
+        progress_bar.bar_mark = '.'
 
         begin
           class << progress_bar
@@ -293,13 +293,13 @@
     def proxy_uri()
       proxy = ENV["#{scheme.upcase}_PROXY"]
       proxy = URI.parse(proxy) if String === proxy
-      excludes = (ENV["NO_PROXY"] || "").split(/\s*,\s*/).compact
+      excludes = ENV['NO_PROXY'].to_s.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?)"
+      fail 'This protocol doesn\'t support writing (yet, how about helping by implementing it?)'
     end
 
   end
@@ -310,7 +310,7 @@
     # See URI::Generic#read
     def read(options = nil, &block)
       options ||= {}
-      headers = { "If-Modified-Since" => CGI.rfc1123_date(options[:modified].utc) } if options[:modified]
+      headers = { 'If-Modified-Since' => CGI.rfc1123_date(options[:modified].utc) } if options[:modified]
 
       if proxy = proxy_uri
         proxy = URI.parse(proxy) if String === proxy
@@ -328,23 +328,23 @@
         #case response = http.request(request)
         when Net::HTTPNotModified
           # No modification, nothing to do.
-          puts "Not modified since last download" if Rake.application.options.trace
+          puts 'Not modified since last download' if Rake.application.options.trace
           return nil
         when Net::HTTPRedirection
           # Try to download from the new URI, handle relative redirects.
           puts "Redirected to #{response['Location']}" if Rake.application.options.trace
-          return (self + URI.parse(response["location"])).read(options, &block)
+          return (self + URI.parse(response['location'])).read(options, &block)
         when Net::HTTPOK
           puts "Downloading #{self}" if verbose
           result = nil
-          with_progress_bar options[:progress], path.split("/").last, response.content_length do |progress|
+          with_progress_bar options[:progress], path.split('/').last, response.content_length do |progress|
             if block
               response.read_body do |chunk|
                 block.call chunk
                 progress << chunk
               end
             else
-              result = ""
+              result = ''
               response.read_body do |chunk|
                 result << chunk
                 progress << chunk
@@ -385,7 +385,7 @@
       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 = "*" }
+          password = HighLine.new.ask("Password for #{host}:") { |q| q.echo = '*' }
           ssh_options[:password] = password
           retry
         end
@@ -393,20 +393,20 @@
       end
 
       session.sftp.connect do |sftp|
-        puts "connected" if Rake.application.options.trace
+        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
-        File.dirname(path).split("/").inject("") do |base, part|
+        File.dirname(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|
+        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|
+          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.
@@ -443,7 +443,7 @@
         end
       end
       # Sadly, file://something really means file://something/ (something being server)
-      set_path "/" if path.empty?
+      set_path '/' if path.empty?
 
       # On windows, file://c:/something is not a valid URL, but people do it anyway, so if we see a drive-as-host,
       # we'll just be nice enough to fix it. (URI actually strips the colon here)
@@ -456,14 +456,14 @@
     # See URI::Generic#read
     def read(options = nil, &block)
       options ||= {}
-      raise ArgumentError, "Either you're attempting to read a file from another host (which we don't support), or you used two slashes by mistake, where you should have file:///<path>." unless host.to_s.blank?
+      raise ArgumentError, 'Either you\'re attempting to read a file from another host (which we don\'t support), or you used two slashes by mistake, where you should have file:///<path>.' unless host.to_s.blank?
 
       path = real_path
       # TODO: complain about clunky URLs
       raise NotFoundError, "Looking for #{self} and can't find it." unless File.exists?(path)
       raise NotFoundError, "Looking for the file #{self}, and it happens to be a directory." if File.directory?(path)
-      File.open path, "rb" do |input|
-        with_progress_bar options[:progress], path.split("/").last, input.stat.size do |progress|
+      File.open path, 'rb' do |input|
+        with_progress_bar options[:progress], path.split('/').last, input.stat.size do |progress|
           block ? block.call(input.read) : input.read
         end
       end
@@ -483,11 +483,11 @@
   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.to_s.blank?
+      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.to_s.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|
+        with_progress_bar options[:progress] && options[:size], path.split('/'), options[:size] || 0 do |progress|
           while chunk = yield(32 * 4096)
             temp.write chunk
             progress << chunk
@@ -500,7 +500,7 @@
       end
     end
 
-    @@schemes["FILE"] = FILE
+    @@schemes['FILE'] = FILE
 
   end
 

Modified: incubator/buildr/trunk/spec/transport_spec.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/transport_spec.rb?rev=612398&r1=612397&r2=612398&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/transport_spec.rb (original)
+++ incubator/buildr/trunk/spec/transport_spec.rb Wed Jan 16 01:42:29 2008
@@ -1,183 +1,183 @@
 require File.join(File.dirname(__FILE__), 'spec_helpers')
 
 
-describe URI, "#download" do
+describe URI, '#download' do
   before do
-    write @source = "source", @content = "Just a file"
+    write @source = 'source', @content = 'Just a file'
     @uri = URI("file://#{File.expand_path(@source)}")
-    @target = "target"
+    @target = 'target'
   end
 
-  it "should download file if found" do
+  it 'should download file if found' do
     @uri.download @target
     file(@target).should contain(@content)
   end
 
-  it "should fail if file not found" do
-    lambda { (@uri + "missing").download @target }.should raise_error(URI::NotFoundError)
+  it 'should fail if file not found' do
+    lambda { (@uri + 'missing').download @target }.should raise_error(URI::NotFoundError)
     file(@target).should_not exist
   end
 
-  it "should work the same way from static method with URI" do
+  it 'should work the same way from static method with URI' do
     URI.download @uri, @target
     file(@target).should contain(@content)
   end
 
-  it "should work the same way from static method with String" do
+  it 'should work the same way from static method with String' do
     URI.download @uri.to_s, @target
     file(@target).should contain(@content)
   end
 
-  it "should download to a task" do
+  it 'should download to a task' do
     @uri.download file(@target)
     file(@target).should contain(@content)
   end
 
-  it "should download to a file" do
-    File.open(@target, "w") { |file| @uri.download file }
+  it 'should download to a file' do
+    File.open(@target, 'w') { |file| @uri.download file }
     file(@target).should contain(@content)
   end
 end
 
 
-describe URI, "#upload" do
+describe URI, '#upload' do
   before do
-    write @source = "source", @content = "Just a file"
-    @target = "target"
+    write @source = 'source', @content = 'Just a file'
+    @target = 'target'
     @uri = URI("file://#{File.expand_path(@target)}")
   end
 
-  it "should upload file if found" do
+  it 'should upload file if found' do
     @uri.upload @source
     file(@target).should contain(@content)
   end
 
-  it "should fail if file not found" do
-    lambda { @uri.upload @source.ext("missing") }.should raise_error(URI::NotFoundError)
+  it 'should fail if file not found' do
+    lambda { @uri.upload @source.ext('missing') }.should raise_error(URI::NotFoundError)
     file(@target).should_not exist
   end
 
-  it "should work the same way from static method with URI" do
+  it 'should work the same way from static method with URI' do
     URI.upload @uri, @source
     file(@target).should contain(@content)
   end
 
-  it "should work the same way from static method with String" do
+  it 'should work the same way from static method with String' do
     URI.upload @uri.to_s, @source
     file(@target).should contain(@content)
   end
 
-  it "should upload from a task" do
+  it 'should upload from a task' do
     @uri.upload file(@source)
     file(@target).should contain(@content)
   end
 
-  it "should create MD5 hash" do
+  it 'should create MD5 hash' do
     @uri.upload file(@source)
-    file(@target.ext(".md5")).should contain(Digest::MD5.hexdigest(@content))
+    file(@target.ext('.md5')).should contain(Digest::MD5.hexdigest(@content))
   end
 
-  it "should create SHA1 hash" do
+  it 'should create SHA1 hash' do
     @uri.upload file(@source)
-    file(@target.ext(".sha1")).should contain(Digest::SHA1.hexdigest(@content))
+    file(@target.ext('.sha1')).should contain(Digest::SHA1.hexdigest(@content))
   end
 
-  it "should upload an entire directory" do
-    mkpath "dir" ; write "dir/test", "in directory"
-    mkpath "dir/nested" ; write "dir/nested/test", "in nested directory"
-    @uri.upload "dir"
-    file(@target).should contain("test", "nested/test")
-    file(@target + "/test").should contain("in directory")
-    file(@target + "/nested/test").should contain("in nested directory")
+  it 'should upload an entire directory' do
+    mkpath 'dir' ; write 'dir/test', 'in directory'
+    mkpath 'dir/nested' ; write 'dir/nested/test', 'in nested directory'
+    @uri.upload 'dir'
+    file(@target).should contain('test', 'nested/test')
+    file(@target + '/test').should contain('in directory')
+    file(@target + '/nested/test').should contain('in nested directory')
   end
 end
 
 
 describe URI::FILE do
-  it "should complain about file:" do
-    lambda { URI("file:") }.should raise_error(URI::InvalidURIError)
+  it 'should complain about file:' do
+    lambda { URI('file:') }.should raise_error(URI::InvalidURIError)
   end
 
-  it "should accept file:something as file:///something" do
-    URI("file:something").should eql(URI("file:///something"))
+  it 'should accept file:something as file:///something' do
+    URI('file:something').should eql(URI('file:///something'))
   end
 
-  it "should accept file:/ as file:///" do
-    URI("file:/").should eql(URI("file:///"))
+  it 'should accept file:/ as file:///' do
+    URI('file:/').should eql(URI('file:///'))
   end
 
-  it "should accept file:/something as file:///something" do
-    URI("file:/something").should eql(URI("file:///something"))
+  it 'should accept file:/something as file:///something' do
+    URI('file:/something').should eql(URI('file:///something'))
   end
 
-  it "should complain about file://" do
-    lambda { URI("file://").should eql(URI("file:///")) }.should raise_error(URI::InvalidURIError)
+  it 'should complain about file://' do
+    lambda { URI('file://').should eql(URI('file:///')) }.should raise_error(URI::InvalidURIError)
   end
 
-  it "should accept file://something as file://something/" do
-    URI("file://something").should eql(URI("file://something/"))
+  it 'should accept file://something as file://something/' do
+    URI('file://something').should eql(URI('file://something/'))
   end
 
-  it "should accept file:///something" do
-    URI("file:///something").should be_kind_of(URI::FILE)
-    URI("file:///something").to_s.should eql("file:///something")
-    URI("file:///something").path.should eql("/something")
+  it 'should accept file:///something' do
+    URI('file:///something').should be_kind_of(URI::FILE)
+    URI('file:///something').to_s.should eql('file:///something')
+    URI('file:///something').path.should eql('/something')
   end
 
-  it "should treat host as path when host name is a Windows drive" do
-    URI("file://c:/something").should eql(URI("file:///c:/something"))
+  it 'should treat host as path when host name is a Windows drive' do
+    URI('file://c:/something').should eql(URI('file:///c:/something'))
   end
 end
 
 
-describe URI::FILE, "#read" do
+describe URI::FILE, '#read' do
   before do
-    @filename = "readme"
+    @filename = 'readme'
     @uri = URI("file:///#{File.expand_path(@filename)}")
-    @content = "Readme. Please!"
-    write "readme", @content
+    @content = 'Readme. Please!'
+    write 'readme', @content
   end
 
-  it "should not complain about excessive options" do
+  it 'should not complain about excessive options' do
     @uri.read :proxy=>[], :lovely=>true
   end
 
-  it "should read the file" do
+  it 'should read the file' do
     @uri.read.should eql(@content)
   end
 
-  it "should read the file and yield to block" do
+  it 'should read the file and yield to block' do
     @uri.read { |content| content.should eql(@content) }
   end
 
-  it "should raise NotFoundError if file doesn't exist" do
-    lambda { (@uri + "notme").read }.should raise_error(URI::NotFoundError)
+  it 'should raise NotFoundError if file doesn\'t exist' do
+    lambda { (@uri + 'notme').read }.should raise_error(URI::NotFoundError)
   end
 
-  it "should raise NotFoundError if file is actually a directory" do
-    mkpath "dir"
-    lambda { (@uri + "dir").read }.should raise_error(URI::NotFoundError)
+  it 'should raise NotFoundError if file is actually a directory' do
+    mkpath 'dir'
+    lambda { (@uri + 'dir').read }.should raise_error(URI::NotFoundError)
   end
 end
 
 
-describe URI::FILE, "#write" do
+describe URI::FILE, '#write' do
   before do
-    @filename = "readme"
+    @filename = 'readme'
     @uri = URI("file:///#{File.expand_path(@filename)}")
-    @content = "Readme. Please!"
+    @content = 'Readme. Please!'
   end
 
-  it "should not complain about excessive options" do
+  it 'should not complain about excessive options' do
     @uri.write @content, :proxy=>[], :lovely=>true
   end
 
-  it "should write the file from a string" do
+  it 'should write the file from a string' do
     @uri.write @content
     read(@filename).should eql(@content)
   end
 
-  it "should write the file from a reader" do
+  it 'should write the file from a reader' do
     reader = Object.new
     class << reader
       def read(bytes) ; @array.pop ; end
@@ -187,13 +187,13 @@
     read(@filename).should eql(@content)
   end
 
-  it "should write the file from a block" do
+  it 'should write the file from a block' do
     array = [@content]
     @uri.write { array.pop }
     read(@filename).should eql(@content)
   end
 
-  it "should not create file if read fails" do
+  it 'should not create file if read fails' do
     @uri.write { fail } rescue nil
     file(@filename).should_not exist
   end
@@ -201,69 +201,76 @@
 
 
 
-describe URI::HTTP, "#read" do
+describe URI::HTTP, '#read' do
   before do
-    @proxy = "http://john:smith@myproxy:8080"
-    @domain = "domain"
+    @proxy = 'http://john:smith@myproxy:8080'
+    @domain = 'domain'
     @host_domain = "host.#{@domain}"
     @uri = URI("http://#{@host_domain}")
     @no_proxy_args = [@host_domain, 80]
-    @proxy_args = @no_proxy_args + ["myproxy", 8080, "john", "smith"]
+    @proxy_args = @no_proxy_args + ['myproxy', 8080, 'john', 'smith']
     @http = mock('http')
-    @http.stub!(:request).and_return(Net::HTTPNotModified.new(nil, nil, nil))
+    @http.stub!(:request).and_yield(Net::HTTPNotModified.new(nil, nil, nil))
   end
 
-  it "should not use proxy unless proxy is set" do
+  it 'should not use proxy unless proxy is set' do
     Net::HTTP.should_receive(:new).with(*@no_proxy_args).and_return(@http)
     @uri.read
   end
 
-  it "should use proxy from environment variable HTTP_PROXY" do
-    ENV["HTTP_PROXY"] = @proxy
+  it 'should use proxy from environment variable HTTP_PROXY' do
+    ENV['HTTP_PROXY'] = @proxy
     Net::HTTP.should_receive(:new).with(*@proxy_args).and_return(@http)
     @uri.read
   end
 
-  it "should not use proxy for hosts from environment variable NO_PROXY" do
-    ENV["HTTP_PROXY"] = @proxy
-    ENV["NO_PROXY"] = @host_domain
+  it 'should not use proxy for hosts from environment variable NO_PROXY' do
+    ENV['HTTP_PROXY'] = @proxy
+    ENV['NO_PROXY'] = @host_domain
     Net::HTTP.should_receive(:new).with(*@no_proxy_args).and_return(@http)
     @uri.read
   end
 
-  it "should use proxy for hosts other than those specified by NO_PROXY" do
-    ENV["HTTP_PROXY"] = @proxy
-    ENV["NO_PROXY"] = "whatever"
+  it 'should use proxy for hosts other than those specified by NO_PROXY' do
+    ENV['HTTP_PROXY'] = @proxy
+    ENV['NO_PROXY'] = 'whatever'
     Net::HTTP.should_receive(:new).with(*@proxy_args).and_return(@http)
     @uri.read
   end
 
-  it "should support comma separated list in environment variable NO_PROXY" do
-    ENV["HTTP_PROXY"] = @proxy
-    ENV["NO_PROXY"] = "optimus,prime"
-    Net::HTTP.should_receive(:new).with("optimus", 80).and_return(@http)
-    URI("http://optimus").read
-    Net::HTTP.should_receive(:new).with("prime", 80).and_return(@http)
-    URI("http://prime").read
-    Net::HTTP.should_receive(:new).with("bumblebee", *@proxy_args[1..-1]).and_return(@http)
-    URI("http://bumblebee").read
+  it 'should support comma separated list in environment variable NO_PROXY' do
+    ENV['HTTP_PROXY'] = @proxy
+    ENV['NO_PROXY'] = 'optimus,prime'
+    Net::HTTP.should_receive(:new).with('optimus', 80).and_return(@http)
+    URI('http://optimus').read
+    Net::HTTP.should_receive(:new).with('prime', 80).and_return(@http)
+    URI('http://prime').read
+    Net::HTTP.should_receive(:new).with('bumblebee', *@proxy_args[1..-1]).and_return(@http)
+    URI('http://bumblebee').read
   end
 
-  it "should support glob pattern in NO_PROXY" do
-    ENV["HTTP_PROXY"] = @proxy
-    ENV["NO_PROXY"] = "*.#{@domain}"
+  it 'should support glob pattern in NO_PROXY' do
+    ENV['HTTP_PROXY'] = @proxy
+    ENV['NO_PROXY'] = "*.#{@domain}"
     Net::HTTP.should_receive(:new).once.with(*@no_proxy_args).and_return(@http)
     @uri.read
   end
 
-  it "should support specific port in NO_PROXY" do
-    ENV["HTTP_PROXY"] = @proxy
-    ENV["NO_PROXY"] = "#{@host_domain}:80"
+  it 'should support specific port in NO_PROXY' do
+    ENV['HTTP_PROXY'] = @proxy
+    ENV['NO_PROXY'] = "#{@host_domain}:80"
     Net::HTTP.should_receive(:new).with(*@no_proxy_args).and_return(@http)
     @uri.read
-    ENV["NO_PROXY"] = "#{@host_domain}:800"
+    ENV['NO_PROXY'] = "#{@host_domain}:800"
     Net::HTTP.should_receive(:new).with(*@proxy_args).and_return(@http)
     @uri.read
   end
 
+  it 'should not die if content size is zero' do
+    ok = Net::HTTPOK.new(nil, nil, nil)
+    ok.stub!(:read_body)
+    @http.stub!(:request).and_yield(ok)
+    Net::HTTP.should_receive(:new).and_return(@http)
+    @uri.read :progress=>true
+  end
 end