86 lines
2.8 KiB
Ruby
86 lines
2.8 KiB
Ruby
require "log4r"
|
|
|
|
require "vagrant/util/platform"
|
|
|
|
module Vagrant
|
|
module Action
|
|
module Builtin
|
|
# This middleware will download a remote box and add it to the
|
|
# given box collection.
|
|
class BoxAdd
|
|
def initialize(app, env)
|
|
@app = app
|
|
@logger = Log4r::Logger.new("vagrant::action::builtin::box_add")
|
|
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)
|
|
|
|
# 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)
|
|
end
|
|
|
|
# Add the box
|
|
env[:ui].info I18n.t("vagrant.actions.box.add.adding", :name => env[:box_name])
|
|
added_box = nil
|
|
begin
|
|
added_box = env[:box_collection].add(
|
|
@temp_path, env[:box_name], env[:box_provider], env[:box_force])
|
|
rescue Vagrant::Errors::BoxUpgradeRequired
|
|
# Upgrade the box
|
|
env[:box_collection].upgrade(env[:box_name])
|
|
|
|
# Try adding it again
|
|
retry
|
|
end
|
|
|
|
# Call the 'recover' method in all cases to clean up the
|
|
# downloaded temporary file.
|
|
recover(env)
|
|
|
|
# Success, we added a box!
|
|
env[:ui].success(
|
|
I18n.t("vagrant.actions.box.add.added", name: added_box.name, provider: added_box.provider))
|
|
|
|
# Carry on!
|
|
@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
|
|
end
|
|
end
|
|
end
|
|
end
|