HTTP downloader implemented. Boxes can now be added via HTTP!
This commit is contained in:
parent
9913c07ff2
commit
3d220ef5c8
|
@ -3,7 +3,7 @@ $:.unshift(libdir)
|
||||||
PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
|
PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
|
||||||
|
|
||||||
# The libs which must be loaded prior to the rest
|
# The libs which must be loaded prior to the rest
|
||||||
%w{tempfile open-uri ftools json pathname logger uri virtualbox net/ssh tarruby
|
%w{tempfile open-uri ftools json pathname logger uri net/http virtualbox net/ssh tarruby
|
||||||
net/scp fileutils vagrant/util vagrant/actions/base vagrant/downloaders/base}.each do |f|
|
net/scp fileutils vagrant/util vagrant/actions/base vagrant/downloaders/base}.each do |f|
|
||||||
require f
|
require f
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,10 +12,13 @@ module Vagrant
|
||||||
def prepare
|
def prepare
|
||||||
# Parse the URI given and prepare a downloader
|
# Parse the URI given and prepare a downloader
|
||||||
uri = URI.parse(@runner.uri)
|
uri = URI.parse(@runner.uri)
|
||||||
|
uri_map = [[URI::HTTP, Downloaders::HTTP], [URI::Generic, Downloaders::File]]
|
||||||
|
|
||||||
if uri.is_a?(URI::Generic)
|
uri_map.find do |uri_type, downloader_klass|
|
||||||
logger.info "Generic URI type for box download, assuming file..."
|
if uri.is_a?(uri_type)
|
||||||
@downloader = Downloaders::File.new
|
logger.info "#{uri_type} for URI, downloading via #{downloader_klass}..."
|
||||||
|
@downloader = downloader_klass.new
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raise ActionException.new("Unknown URI type for box download.") unless @downloader
|
raise ActionException.new("Unknown URI type for box download.") unless @downloader
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
module Vagrant
|
||||||
|
module Downloaders
|
||||||
|
# Downloads a file from an HTTP URL to a temporary file. This
|
||||||
|
# downloader reports its progress to stdout while downloading.
|
||||||
|
class HTTP < Base
|
||||||
|
# ANSI escape code to clear lines from cursor to end of line
|
||||||
|
CL_RESET = "\r\e[0K"
|
||||||
|
|
||||||
|
def download!(source_url, destination_file)
|
||||||
|
Net::HTTP.get_response(URI.parse(source_url)) do |response|
|
||||||
|
total = response.content_length
|
||||||
|
progress = 0
|
||||||
|
segment_count = 0
|
||||||
|
|
||||||
|
response.read_body do |segment|
|
||||||
|
# Report the progress out
|
||||||
|
progress += segment.length
|
||||||
|
segment_count += 1
|
||||||
|
|
||||||
|
# Progress reporting is limited to every 25 segments just so
|
||||||
|
# we're not constantly updating
|
||||||
|
if segment_count % 25 == 0
|
||||||
|
report_progress(progress, total)
|
||||||
|
segment_count = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Store the segment
|
||||||
|
destination_file.write(segment)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def report_progress(progress, total)
|
||||||
|
percent = (progress.to_f / total.to_f) * 100
|
||||||
|
print "#{CL_RESET}Download Progress: #{percent.to_i}% (#{progress} / #{total})"
|
||||||
|
$stdout.flush
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -30,6 +30,12 @@ class DownloadBoxActionTest < Test::Unit::TestCase
|
||||||
@action.prepare
|
@action.prepare
|
||||||
assert @action.downloader.is_a?(Vagrant::Downloaders::File)
|
assert @action.downloader.is_a?(Vagrant::Downloaders::File)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
should "set the downloader to HTTP if URI is HTTP" do
|
||||||
|
@uri.stubs(:is_a?).with(URI::HTTP).returns(true)
|
||||||
|
@action.prepare
|
||||||
|
assert @action.downloader.is_a?(Vagrant::Downloaders::HTTP)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "executing" do
|
context "executing" do
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
||||||
|
|
||||||
|
class HttpDownloaderTest < Test::Unit::TestCase
|
||||||
|
setup do
|
||||||
|
@downloader, @tempfile = mock_downloader(Vagrant::Downloaders::HTTP)
|
||||||
|
@downloader.stubs(:report_progress)
|
||||||
|
@uri = "foo.box"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "downloading" do
|
||||||
|
setup do
|
||||||
|
@parsed_uri = mock("parsed")
|
||||||
|
URI.stubs(:parse).with(@uri).returns(@parsed_uri)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "parse the URI and use that parsed URI for Net::HTTP" do
|
||||||
|
URI.expects(:parse).with(@uri).returns(@parsed_uri).once
|
||||||
|
Net::HTTP.expects(:get_response).with(@parsed_uri).once
|
||||||
|
@downloader.download!(@uri, @tempfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "read the body of the response and place each segment into the file" do
|
||||||
|
response = mock("response")
|
||||||
|
response.stubs(:content_length)
|
||||||
|
segment = mock("segment")
|
||||||
|
segment.stubs(:length).returns(7)
|
||||||
|
|
||||||
|
Net::HTTP.stubs(:get_response).yields(response)
|
||||||
|
response.expects(:read_body).once.yields(segment)
|
||||||
|
@tempfile.expects(:write).with(segment).once
|
||||||
|
|
||||||
|
@downloader.download!(@uri, @tempfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "reporting progress" do
|
||||||
|
# TODO: Testing for this, probably
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue