Download boxes using CURL!
This commit is contained in:
parent
94dd210be7
commit
6c1eb2b007
|
@ -1,5 +1,6 @@
|
|||
require "log4r"
|
||||
|
||||
require "vagrant/util/downloader"
|
||||
require "vagrant/util/platform"
|
||||
|
||||
module Vagrant
|
||||
|
@ -14,18 +15,21 @@ module Vagrant
|
|||
end
|
||||
|
||||
def call(env)
|
||||
# Instantiate the downloader
|
||||
downloader = download_klass(env[:box_url]).new(env[:ui])
|
||||
env[:ui].info I18n.t("vagrant.actions.box.download.with",
|
||||
:class => downloader.class.to_s)
|
||||
@temp_path = env[:tmp_path].join("box" + Time.now.to_i.to_s)
|
||||
@logger.info("Downloading box to: #{@temp_path}")
|
||||
|
||||
# Download the box to a temporary path. We store the temporary
|
||||
# path as an instance variable so that the `#recover` method can
|
||||
# access it.
|
||||
@temp_path = env[:tmp_path].join("box" + Time.now.to_i.to_s)
|
||||
@logger.info("Downloading box to: #{@temp_path}")
|
||||
File.open(@temp_path, Vagrant::Util::Platform.tar_file_options) do |f|
|
||||
downloader.download!(env[:box_url], f)
|
||||
env[:ui].info(I18n.t("vagrant.actions.box.download.downloading"))
|
||||
begin
|
||||
downloader = Util::Downloader.new(env[:box_url], @temp_path, :ui => env[:ui])
|
||||
downloader.download!
|
||||
rescue Errors::DownloaderInterrupted
|
||||
# The downloader was interrupted, so just return, because that
|
||||
# means we were interrupted as well.
|
||||
env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted"))
|
||||
return
|
||||
end
|
||||
|
||||
# Add the box
|
||||
|
@ -54,28 +58,8 @@ module Vagrant
|
|||
@app.call(env)
|
||||
end
|
||||
|
||||
def download_klass(url)
|
||||
# This is hardcoded for now. In the future I'd like to make this
|
||||
# pluginnable as well.
|
||||
classes = [Downloaders::HTTP, Downloaders::File]
|
||||
|
||||
# Find the class to use.
|
||||
classes.each_index do |i|
|
||||
klass = classes[i]
|
||||
|
||||
# Use the class if it matches the given URI or if this
|
||||
# is the last class...
|
||||
return klass if classes.length == (i + 1) || klass.match?(url)
|
||||
end
|
||||
|
||||
# If no downloader knows how to download this file, then we
|
||||
# raise an exception.
|
||||
raise Errors::BoxDownloadUnknownType
|
||||
end
|
||||
|
||||
def recover(env)
|
||||
if @temp_path && File.exist?(@temp_path)
|
||||
env[:ui].info I18n.t("vagrant.actions.box.download.cleaning")
|
||||
File.unlink(@temp_path)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -95,10 +95,6 @@ module Vagrant
|
|||
error_key(:already_exists, "vagrant.actions.box.unpackage")
|
||||
end
|
||||
|
||||
class BoxDownloadUnknownType < VagrantError
|
||||
error_key(:unknown_type, "vagrant.actions.box.download")
|
||||
end
|
||||
|
||||
class BoxMetadataFileNotFound < VagrantError
|
||||
error_key(:box_metadata_file_not_found)
|
||||
end
|
||||
|
@ -167,6 +163,10 @@ module Vagrant
|
|||
error_key(:downloader_error)
|
||||
end
|
||||
|
||||
class DownloaderInterrupted < DownloaderError
|
||||
error_key(:downloader_interrupted)
|
||||
end
|
||||
|
||||
class DownloaderFileDoesntExist < VagrantError
|
||||
error_key(:file_missing, "vagrant.downloaders.file")
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require "log4r"
|
||||
|
||||
require "vagrant/util/busy"
|
||||
require "vagrant/util/subprocess"
|
||||
|
||||
module Vagrant
|
||||
|
@ -10,12 +11,12 @@ module Vagrant
|
|||
class Downloader
|
||||
def initialize(source, destination, options=nil)
|
||||
@logger = Log4r::Logger.new("vagrant::util::downloader")
|
||||
@source = source
|
||||
@destination = destination
|
||||
@source = source.to_s
|
||||
@destination = destination.to_s
|
||||
|
||||
# Get the various optional values
|
||||
@options ||= {}
|
||||
@ui = @options[:ui]
|
||||
options ||= {}
|
||||
@ui = options[:ui]
|
||||
end
|
||||
|
||||
# This executes the actual download, downloading the source file
|
||||
|
@ -70,24 +71,38 @@ module Vagrant
|
|||
# 11 - Time left
|
||||
# 12 - Current speed
|
||||
|
||||
output = "Progress: #{columns[1]}% (Rate: #{columns[12]}/s, Estimated time remaining: #{columns[11]}"
|
||||
output = "Progress: #{columns[1]}% (Rate: #{columns[12]}/s, Estimated time remaining: #{columns[11]})"
|
||||
@ui.clear_line
|
||||
@ui.info(output, :new_line => false)
|
||||
end
|
||||
end
|
||||
|
||||
# Create the callback that is called if we are interrupted
|
||||
interrupted = false
|
||||
int_callback = Proc.new do
|
||||
@logger.info("Downloader interrupted!")
|
||||
interrupted = true
|
||||
end
|
||||
|
||||
@logger.info("Downloader starting download: ")
|
||||
@logger.info(" -- Source: #{@source}")
|
||||
@logger.info(" -- Destination: #{@destination}")
|
||||
|
||||
# Execute!
|
||||
result = Subprocess.execute("curl", *options, &data_proc)
|
||||
result = Busy.busy(int_callback) do
|
||||
Subprocess.execute("curl", *options, &data_proc)
|
||||
end
|
||||
|
||||
# If the download was interrupted, then raise a specific error
|
||||
raise Errors::DownloaderInterrupted if interrupted
|
||||
|
||||
# If it didn't exit successfully, we need to parse the data and
|
||||
# show an error message.
|
||||
if result.exit_code != 0
|
||||
parts = result.stderr.split(/\ncurl:\s+\(\d+\)\s*/, 2)
|
||||
raise Errors::DownloaderError, :message => parts[1]
|
||||
@logger.warn("Downloader exit code: #{result.exit_code}")
|
||||
parts = result.stderr.split(/\n*curl:\s+\(\d+\)\s*/, 2)
|
||||
parts[1] ||= ""
|
||||
raise Errors::DownloaderError, :message => parts[1].chomp
|
||||
end
|
||||
|
||||
# Everything succeeded
|
||||
|
|
|
@ -136,6 +136,9 @@ en:
|
|||
again.
|
||||
|
||||
%{message}
|
||||
downloader_interrupted: |-
|
||||
The download was interrupted by an external signal. It did not
|
||||
complete.
|
||||
environment_locked: |-
|
||||
An instance of Vagrant is already running. Only one instance of Vagrant
|
||||
may run at any given time to avoid problems with VirtualBox inconsistencies
|
||||
|
@ -853,9 +856,9 @@ en:
|
|||
destroy:
|
||||
destroying: "Deleting box '%{name}'..."
|
||||
download:
|
||||
with: "Downloading with %{class}..."
|
||||
cleaning: "Cleaning up downloaded box..."
|
||||
unknown_type: "Unknown or unsupported URI type given for box download."
|
||||
downloading: "Downloading or copying the box..."
|
||||
interrupted: "Box download was interrupted. Exiting."
|
||||
verify:
|
||||
verifying: "Verifying box..."
|
||||
failed: |-
|
||||
|
|
Loading…
Reference in New Issue