diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index eec35987f..2a8d9c6ad 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -8,7 +8,8 @@ module Vagrant # Builtin contains middleware classes that are shipped with Vagrant-core # and are thus available to all plugins as a "standard library" of sorts. module Builtin - autoload :BoxAdd, "vagrant/action/builtin/box_add" + autoload :BoxAdd, "vagrant/action/builtin/box_add" + autoload :BoxRemove, "vagrant/action/builtin/box_remove" autoload :Call, "vagrant/action/builtin/call" autoload :Confirm, "vagrant/action/builtin/confirm" autoload :ConfigValidate, "vagrant/action/builtin/config_validate" @@ -41,5 +42,14 @@ module Vagrant b.use Builtin::BoxAdd end end + + # This is the action that will remove a box given a name (and optionally + # a provider). This middleware sequence is built-in to Vagrant. Plugins + # can hook into this like any other middleware sequence. + def self.action_box_remove + Builder.new.tap do |b| + b.use Builtin::BoxRemove + end + end end end diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index 01adb0e18..74210fe22 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -81,9 +81,9 @@ module Vagrant # Add the box env[:ui].info I18n.t("vagrant.actions.box.add.adding", :name => env[:box_name]) - added_box = nil + box_added = nil begin - added_box = env[:box_collection].add( + box_added = env[:box_collection].add( @temp_path, env[:box_name], box_formats, env[:box_force]) rescue Vagrant::Errors::BoxUpgradeRequired # Upgrade the box @@ -99,7 +99,13 @@ module Vagrant # Success, we added a box! env[:ui].success( - I18n.t("vagrant.actions.box.add.added", name: added_box.name, provider: added_box.provider)) + I18n.t("vagrant.actions.box.add.added", name: box_added.name, provider: box_added.provider)) + + # Persists URL used on download and the time it was added + write_extra_info(box_added, url) + + # Passes on the newly added box to the rest of the middleware chain + env[:box_added] = box_added # Carry on! @app.call(env) @@ -110,6 +116,13 @@ module Vagrant File.unlink(@temp_path) end end + + def write_extra_info(box_added, url) + info = {'url' => url, 'downloaded_at' => Time.now.utc} + box_added.directory.join('info.json').open("w+") do |f| + f.write(JSON.dump(info)) + end + end end end end diff --git a/lib/vagrant/action/builtin/box_remove.rb b/lib/vagrant/action/builtin/box_remove.rb new file mode 100644 index 000000000..3ae8bc1ac --- /dev/null +++ b/lib/vagrant/action/builtin/box_remove.rb @@ -0,0 +1,38 @@ +require "log4r" + +module Vagrant + module Action + module Builtin + # This middleware will remove a box for a given provider. + class BoxRemove + def initialize(app, env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::builtin::box_remove") + end + + def call(env) + box_name = env[:box_name] + box_provider = env[:box_provider].to_sym + + box = nil + begin + box = env[:box_collection].find(box_name, box_provider) + rescue Vagrant::Errors::BoxUpgradeRequired + @env.boxes.upgrade(box_name) + retry + end + + raise Vagrant::Errors::BoxNotFound, :name => box_name, :provider => box_provider if !box + env[:ui].info(I18n.t("vagrant.commands.box.removing", + :name => box_name, + :provider => box_provider)) + box.destroy! + + # Passes on the removed box to the rest of the middleware chain + env[:box_removed] = box + @app.call(env) + end + end + end + end +end diff --git a/plugins/commands/box/command/add.rb b/plugins/commands/box/command/add.rb index 1f5f9be5f..99c87ac58 100644 --- a/plugins/commands/box/command/add.rb +++ b/plugins/commands/box/command/add.rb @@ -44,7 +44,7 @@ module VagrantPlugins :box_url => argv[1], :box_clean => options[:clean], :box_force => options[:force], - :box_download_insecure => options[:insecure], + :box_download_insecure => options[:insecure] }) # Success, exit status 0 diff --git a/plugins/commands/box/command/list.rb b/plugins/commands/box/command/list.rb index 033c07d1c..4bfa12181 100644 --- a/plugins/commands/box/command/list.rb +++ b/plugins/commands/box/command/list.rb @@ -9,6 +9,11 @@ module VagrantPlugins opts = OptionParser.new do |opts| opts.banner = "Usage: vagrant box list" + opts.separator "" + + opts.on("-i", "--box-info", "Displays additional information about the boxes.") do |i| + options[:info] = i + end end # Parse the options @@ -20,10 +25,23 @@ module VagrantPlugins return @env.ui.warn(I18n.t("vagrant.commands.box.no_installed_boxes"), :prefix => false) end + list_boxes(boxes, options[:info]) + + # Success, exit status 0 + 0 + end + + private + + def list_boxes(boxes, extra_info) # Find the longest box name longest_box = boxes.max_by { |x| x[0].length } longest_box_length = longest_box[0].length + # Find the longest provider name + longest_provider = boxes.max_by { |x| x[1].length } + longest_provider_length = longest_provider[1].length + # Go through each box and output the information about it. We # ignore the "v1" param for now since I'm not yet sure if its # important for the user to know what boxes need to be upgraded @@ -33,10 +51,29 @@ module VagrantPlugins @env.ui.machine("box-name", name) @env.ui.machine("box-provider", provider) - end - # Success, exit status 0 - 0 + extra = '' + if extra_info + extra << format_extra_info(name.to_s, provider.to_s) + end + + name = name.ljust(longest_box_length) + provider = "(#{provider})".ljust(longest_provider_length + 2) # 2 -> parenthesis + box_info = "#{name} #{provider}#{extra}" + + @env.ui.info(box_info, :prefix => false) + end + end + + def format_extra_info(name, provider) + info_json = @env.boxes.find(name, provider).directory.join('info.json') + if info_json.file? + info = JSON.parse(info_json.read) + return "\n `- URL: #{info['url']}" + + "\n `- Date: #{info['downloaded_at']}" + else + return '' + end end end end diff --git a/plugins/commands/box/command/remove.rb b/plugins/commands/box/command/remove.rb index 4cdfcdfa4..d58f5bcec 100644 --- a/plugins/commands/box/command/remove.rb +++ b/plugins/commands/box/command/remove.rb @@ -34,19 +34,10 @@ module VagrantPlugins argv[1] = providers[0] || "" end - b = nil - begin - b = @env.boxes.find(argv[0], argv[1].to_sym) - rescue Vagrant::Errors::BoxUpgradeRequired - @env.boxes.upgrade(argv[0]) - retry - end - - raise Vagrant::Errors::BoxNotFound, :name => argv[0], :provider => argv[1].to_sym if !b - @env.ui.info(I18n.t("vagrant.commands.box.removing", - :name => argv[0], - :provider => argv[1])) - b.destroy! + @env.action_runner.run(Vagrant::Action.action_box_remove, { + :box_name => argv[0], + :box_provider => argv[1] + }) # Success, exit status 0 0