diff --git a/lib/vagrant/actions/box/add.rb b/lib/vagrant/actions/box/add.rb index b46ba2c3d..98a119b81 100644 --- a/lib/vagrant/actions/box/add.rb +++ b/lib/vagrant/actions/box/add.rb @@ -4,6 +4,7 @@ module Vagrant class Add < Base def prepare @runner.add_action(Download) + @runner.add_action(Unpackage) end end end diff --git a/lib/vagrant/actions/box/download.rb b/lib/vagrant/actions/box/download.rb index 4d394e00a..ed1bfc204 100644 --- a/lib/vagrant/actions/box/download.rb +++ b/lib/vagrant/actions/box/download.rb @@ -10,6 +10,7 @@ module Vagrant def execute! with_tempfile do |tempfile| copy_uri_to(tempfile) + @runner.temp_path = tempfile.path end end @@ -20,6 +21,8 @@ module Vagrant end end + # TODO: Need a way to report progress. Downloading/copying a 350 MB + # box without any progress is not acceptable. def copy_uri_to(f) logger.info "Copying box to temporary location..." open(@runner.uri) do |remote_file| diff --git a/lib/vagrant/actions/box/unpackage.rb b/lib/vagrant/actions/box/unpackage.rb new file mode 100644 index 000000000..5b8542695 --- /dev/null +++ b/lib/vagrant/actions/box/unpackage.rb @@ -0,0 +1,38 @@ +module Vagrant + module Actions + module Box + class Unpackage < Base + TAR_OPTIONS = [File::RDONLY, 0644, Tar::GNU] + + def execute! + setup_box_dir + decompress + end + + def setup_box_dir + if File.directory?(box_dir) + error_and_exit(<<-msg) +This box appears to already exist! Please call `vagrant box remove #{@runner.name}` +and then try to add it again. +msg + end + + FileUtils.mkdir_p(box_dir) + end + + def box_dir + File.join(Env.boxes_path, @runner.name) + end + + def decompress + Dir.chdir(box_dir) do + logger.info "Extracting box to #{box_dir}..." + Tar.open(@runner.temp_path, *TAR_OPTIONS) do |tar| + tar.extract_all + end + end + end + end + end + end +end \ No newline at end of file diff --git a/lib/vagrant/env.rb b/lib/vagrant/env.rb index 5c55c6e19..3972eb1c5 100644 --- a/lib/vagrant/env.rb +++ b/lib/vagrant/env.rb @@ -15,6 +15,7 @@ module Vagrant def dotfile_path; File.join(root_path, Vagrant.config.dotfile_name); end def home_path; File.expand_path(Vagrant.config.vagrant.home); end def tmp_path; File.join(home_path, "tmp"); end + def boxes_path; File.join(home_path, "boxes"); end def load! load_root_path! diff --git a/test/vagrant/actions/box/add_test.rb b/test/vagrant/actions/box/add_test.rb index 36c0e4821..0eef239e1 100644 --- a/test/vagrant/actions/box/add_test.rb +++ b/test/vagrant/actions/box/add_test.rb @@ -2,9 +2,25 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper') class AddBoxActionTest < Test::Unit::TestCase setup do - @wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Box::Add) + @runner, @vm, @action = mock_action(Vagrant::Actions::Box::Add) mock_config end - # TODO: Everything, once add does anything. + context "sub-actions" do + setup do + @default_order = [Vagrant::Actions::Box::Download, Vagrant::Actions::Box::Unpackage] + end + + def setup_action_expectations + default_seq = sequence("default_seq") + @default_order.each do |action| + @runner.expects(:add_action).with(action).once.in_sequence(default_seq) + end + end + + should "do the proper actions by default" do + setup_action_expectations + @action.prepare + end + end end diff --git a/test/vagrant/actions/box/download_test.rb b/test/vagrant/actions/box/download_test.rb index 81faa1f28..6af5b00ca 100644 --- a/test/vagrant/actions/box/download_test.rb +++ b/test/vagrant/actions/box/download_test.rb @@ -5,6 +5,7 @@ class DownloadBoxActionTest < Test::Unit::TestCase @uri = "foo.com" @runner, @vm, @action = mock_action(Vagrant::Actions::Box::Download) @runner.stubs(:uri).returns(@uri) + @runner.stubs(:temp_path=) mock_config Vagrant::Env.stubs(:tmp_path).returns("foo") @@ -12,7 +13,13 @@ class DownloadBoxActionTest < Test::Unit::TestCase context "executing" do setup do + @path = "foo" + @tempfile = mock("tempfile") + @tempfile.stubs(:path).returns(@path) + + @action.stubs(:with_tempfile).yields(@tempfile) + @action.stubs(:copy_uri_to) end should "make a tempfile and copy the URI contents to it" do @@ -20,6 +27,11 @@ class DownloadBoxActionTest < Test::Unit::TestCase @action.expects(:copy_uri_to).with(@tempfile) @action.execute! end + + should "save the tempfile path" do + @runner.expects(:temp_path=).with(@path).once + @action.execute! + end end context "tempfile" do diff --git a/test/vagrant/actions/box/unpackage_test.rb b/test/vagrant/actions/box/unpackage_test.rb new file mode 100644 index 000000000..37860688f --- /dev/null +++ b/test/vagrant/actions/box/unpackage_test.rb @@ -0,0 +1,73 @@ +require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper') + +class UnpackageBoxActionTest < Test::Unit::TestCase + setup do + @runner, @vm, @action = mock_action(Vagrant::Actions::Box::Unpackage) + @runner.stubs(:name).returns("foo") + @runner.stubs(:temp_path).returns("bar") + mock_config + + Vagrant::Env.stubs(:boxes_path).returns("bar") + end + + context "executing" do + should "execute the proper actions in the proper order" do + exec_seq = sequence("exec_seq") + @action.expects(:setup_box_dir).in_sequence(exec_seq) + @action.expects(:decompress).in_sequence(exec_seq) + @action.execute! + end + end + + context "box directory" do + setup do + @box_dir = File.join(Vagrant::Env.boxes_path, @runner.name) + end + + should "return the boxes_path joined with the name" do + assert_equal @box_dir, @action.box_dir + end + end + + context "setting up the box directory" do + setup do + File.stubs(:directory?).returns(false) + FileUtils.stubs(:mkdir_p) + + @box_dir = "foo" + @action.stubs(:box_dir).returns(@box_dir) + end + + should "error and exit if the directory exists" do + File.expects(:directory?).returns(true) + @action.expects(:error_and_exit).once + @action.setup_box_dir + end + + should "create the directory" do + FileUtils.expects(:mkdir_p).with(@box_dir).once + @action.setup_box_dir + end + end + + context "decompressing" do + setup do + @box_dir = "foo" + + @action.stubs(:box_dir).returns(@box_dir) + Dir.stubs(:chdir).yields + end + + should "change to the box directory" do + Dir.expects(:chdir).with(@box_dir) + @action.decompress + end + + should "open the tar file within the new directory, and extract it all" do + @tar = mock("tar") + @tar.expects(:extract_all).once + Tar.expects(:open).with(@runner.temp_path, anything, anything, anything).yields(@tar) + @action.decompress + end + end +end diff --git a/test/vagrant/env_test.rb b/test/vagrant/env_test.rb index 0bac91fa4..dc98a77ab 100644 --- a/test/vagrant/env_test.rb +++ b/test/vagrant/env_test.rb @@ -191,5 +191,11 @@ class EnvTest < Test::Unit::TestCase Vagrant::Env.stubs(:home_path).returns(@home_path) assert_equal File.join(@home_path, "tmp"), Vagrant::Env.tmp_path end + + should "return the boxes path" do + @home_path = "foo" + Vagrant::Env.stubs(:home_path).returns(@home_path) + assert_equal File.join(@home_path, "boxes"), Vagrant::Env.boxes_path + end end end