diff --git a/lib/vagrant/box_collection2.rb b/lib/vagrant/box_collection2.rb index 88fa015a6..276f08113 100644 --- a/lib/vagrant/box_collection2.rb +++ b/lib/vagrant/box_collection2.rb @@ -1,3 +1,5 @@ +require "digest/sha1" + require "log4r" module Vagrant @@ -89,6 +91,53 @@ module Vagrant nil end + # Upgrades a V1 box with the given name to a V2 box. If a box with the + # given name doesn't exist, then a `BoxNotFound` exception will be raised. + # If the given box is found but is not a V1 box then `true` is returned + # because this just works fine. + # + # @return [Boolean] `true` otherwise an exception is raised. + def upgrade(name) + box_dir = @directory.join(name) + + # If the box doesn't exist at all, raise an exception + raise Errors::BoxNotFound, :name => name if !box_dir.directory? + + if v1_box?(name) + # First, we create a temporary directory within the box to store + # the intermediary moved files. We randomize this in case there is + # already a directory named "virtualbox" in here for some reason. + temp_dir = box_dir.join("vagrant-#{Digest::SHA1.hexdigest(name)}") + + # Make the temporary directory + temp_dir.mkpath + + # Move all the things into the temporary directory + box_dir.children(true).each do |child| + # Don't move the temp_dir + next if child == temp_dir + + # Move every other directory into the temporary directory + FileUtils.mv(child, temp_dir.join(child.basename)) + end + + # If there is no metadata.json file, make one, since this is how + # we determine if the box is a V2 box. + metadata_file = temp_dir.join("metadata.json") + if !metadata_file.file? + metadata_file.open("w") do |f| + f.write(JSON.generate({})) + end + end + + # Rename the temporary directory to the provider. + temp_dir.rename(box_dir.join("virtualbox")) + end + + # We did it! Or the v1 box didn't exist so it doesn't matter. + return true + end + protected # This checks if the given name represents a V1 box on the system. diff --git a/test/unit/vagrant/box_collection2_test.rb b/test/unit/vagrant/box_collection2_test.rb index d0954a9bc..d412354fb 100644 --- a/test/unit/vagrant/box_collection2_test.rb +++ b/test/unit/vagrant/box_collection2_test.rb @@ -62,4 +62,35 @@ describe Vagrant::BoxCollection2 do to raise_error(Vagrant::Errors::BoxUpgradeRequired) end end + + describe "upgrading" do + it "should upgrade a V1 box to V2" do + # Create a V1 box + environment.box1("foo") + + # Verify that only a V1 box exists + expect { instance.find("foo", :virtualbox) }. + to raise_error(Vagrant::Errors::BoxUpgradeRequired) + + # Upgrade the box + instance.upgrade("foo").should be + + # Verify the box exists + box = instance.find("foo", :virtualbox) + box.should_not be_nil + box.name.should == "foo" + end + + it "should raise a BoxNotFound exception if a non-existent box is upgraded" do + expect { instance.upgrade("i-dont-exist") }. + to raise_error(Vagrant::Errors::BoxNotFound) + end + + it "should return true if we try to upgrade a V2 box" do + # Create a V2 box + environment.box2("foo", :vmware) + + instance.upgrade("foo").should be + end + end end