diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index e43559ecb..7da36c9b1 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -31,7 +31,8 @@ module Vagrant # Add the box env[:ui].info I18n.t("vagrant.actions.box.add.adding", :name => env[:box_name]) begin - env[:box_collection].add(@temp_path, env[:box_name], env[:box_provider]) + 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]) diff --git a/lib/vagrant/box_collection.rb b/lib/vagrant/box_collection.rb index 68065c76a..25366330b 100644 --- a/lib/vagrant/box_collection.rb +++ b/lib/vagrant/box_collection.rb @@ -63,14 +63,23 @@ module Vagrant # will be verified with the `metadata.json` file in the box and is # meant as a basic check. If this isn't given, then whatever provider # the box represents will be added. - def add(path, name, provider=nil) + # @param [Boolean] force If true, any existing box with the same name + # and provider will be replaced. + def add(path, name, provider=nil, force=false) # A helper to check if a box exists. We store this in a variable # since we call it multiple times. check_box_exists = lambda do |box_provider| - if find(name, box_provider) + box = find(name, box_provider) + next if !box + + if !force @logger.error("Box already exists, can't add: #{name} #{box_provider}") raise Errors::BoxAlreadyExists, :name => name, :provider => box_provider end + + # We're forcing, so just delete the old box + @logger.info("Box already exists, but forcing so removing: #{name} #{box_provider}") + box.destroy! end log_provider = provider ? provider : "any provider" diff --git a/plugins/commands/box/command/add.rb b/plugins/commands/box/command/add.rb index 863444eab..42ab6e583 100644 --- a/plugins/commands/box/command/add.rb +++ b/plugins/commands/box/command/add.rb @@ -26,13 +26,6 @@ module VagrantPlugins return if !argv raise Vagrant::Errors::CLIInvalidUsage, :help => opts.help.chomp if argv.length < 2 - # If we're force adding, then be sure to destroy any existing box if it - # exists. - if options[:force] - existing = @env.boxes.find(argv[0], :virtualbox) - existing.destroy! if existing - end - # Get the provider if one was set provider = nil provider = options[:provider].to_sym if options[:provider] @@ -40,7 +33,8 @@ module VagrantPlugins @env.action_runner.run(Vagrant::Action.action_box_add, { :box_name => argv[0], :box_provider => provider, - :box_url => argv[1] + :box_url => argv[1], + :box_force => options[:force] }) # Success, exit status 0 diff --git a/test/unit/support/isolated_environment.rb b/test/unit/support/isolated_environment.rb index ea897a4c4..7e2f304ba 100644 --- a/test/unit/support/isolated_environment.rb +++ b/test/unit/support/isolated_environment.rb @@ -129,12 +129,14 @@ module Unit # # @param [Symbol] provider Provider for the box. # @return [Pathname] Path to the newly created box. - def box2_file(provider) + def box2_file(provider, options=nil) + options ||= {} + # This is the metadata we want to store in our file metadata = { "type" => "v2_box", "provider" => provider - } + }.merge(options[:metadata] || {}) # Create a temporary directory to store our data we will tar up td_source = Tempdir.new diff --git a/test/unit/vagrant/box_collection_test.rb b/test/unit/vagrant/box_collection_test.rb index 59f0e3d12..9a22a26a0 100644 --- a/test/unit/vagrant/box_collection_test.rb +++ b/test/unit/vagrant/box_collection_test.rb @@ -63,6 +63,19 @@ describe Vagrant::BoxCollection do to raise_error(Vagrant::Errors::BoxAlreadyExists) end + it "should replace the box if force is specified" do + prev_box_name = "foo" + prev_box_provider = :vmware + + # Setup the environment with the box pre-added + environment.box2(prev_box_name, prev_box_provider) + + # Attempt to add the box with the same name + box_path = environment.box2_file(prev_box_provider, metadata: { "replaced" => "yes" }) + box = instance.add(box_path, prev_box_name, nil, true) + box.metadata["replaced"].should == "yes" + end + it "should raise an exception if the box already exists and no provider is given" do # Create some box file box_name = "foo"