diff --git a/lib/vagrant/action/builtin.rb b/lib/vagrant/action/builtin.rb index cd7600980..8377d293b 100644 --- a/lib/vagrant/action/builtin.rb +++ b/lib/vagrant/action/builtin.rb @@ -15,6 +15,7 @@ module Vagrant # start - Starts a VM, assuming it already exists on the # environment. start = Builder.new do + use VM::CleanMachineFolder use VM::Customize use VM::ClearForwardedPorts use VM::ForwardPorts @@ -75,6 +76,7 @@ module Vagrant use VM::ClearNFSExports use VM::DestroyUnusedNetworkInterfaces use VM::Destroy + use VM::CleanMachineFolder end register :destroy, destroy diff --git a/lib/vagrant/action/vm/clean_machine_folder.rb b/lib/vagrant/action/vm/clean_machine_folder.rb new file mode 100644 index 000000000..6f8172f73 --- /dev/null +++ b/lib/vagrant/action/vm/clean_machine_folder.rb @@ -0,0 +1,37 @@ +require 'fileutils' + +module Vagrant + class Action + module VM + # Cleans up the VirtualBox machine folder for any ".xml-prev" + # files which VirtualBox may have left over. This is a bug in + # VirtualBox. As soon as this is fixed, this middleware can and + # will be removed. + class CleanMachineFolder + def initialize(app, env) + @app = app + end + + def call(env) + clean_machine_folder + @app.call(env) + end + + def clean_machine_folder + folder = File.join(VirtualBox::Global.global.system_properties.default_machine_folder, "*") + Dir[folder].each do |f| + next unless File.directory?(f) + + keep = Dir["#{f}/**/*"].find do |d| + # Find a file that doesn't have ".xml-prev" as the suffix, + # which signals that we want to keep this folder + File.file?(d) && !(File.basename(d) =~ /\.xml-prev$/) + end + + FileUtils.rm_rf(f) if !keep + end + end + end + end + end +end diff --git a/test/vagrant/action/vm/clean_machine_folder_test.rb b/test/vagrant/action/vm/clean_machine_folder_test.rb new file mode 100644 index 000000000..90b1ef06c --- /dev/null +++ b/test/vagrant/action/vm/clean_machine_folder_test.rb @@ -0,0 +1,77 @@ +require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper') + +class CleanMachineFolderVMActionTest < Test::Unit::TestCase + setup do + @klass = Vagrant::Action::VM::CleanMachineFolder + @app, @env = mock_action_data + + @instance = @klass.new(@app, @env) + end + + context "calling" do + should "clean machine folder then continue chain" do + seq = sequence("seq") + @instance.expects(:clean_machine_folder).in_sequence(seq) + @app.expects(:call).with(@env).in_sequence(seq) + @instance.call(@env) + end + end + + context "cleaning the folder" do + setup do + @machine_folder = "foo" + @folder = File.join(@machine_folder, "*") + VirtualBox::Global.global.system_properties.stubs(:default_machine_folder).returns(@machine_folder) + File.stubs(:file?).returns(true) + end + + should "ignore all non-directories" do + folders = %W[foo bar baz] + Dir.expects(:[]).with(@folder).returns(folders) + folders.each do |f| + File.expects(:directory?).with(f).returns(false) + end + + FileUtils.expects(:rm_rf).never + + @instance.clean_machine_folder + end + + should "delete directories with only .xml-prev files" do + folders = { + "sfoo" => %W[foo bar baz.xml-prev], + "sbar" => %W[foo.xml-prev] + } + + Dir.expects(:[]).with(@folder).returns(folders.keys) + folders.each do |folder, subfolders| + File.expects(:directory?).with(folder).returns(true) + Dir.expects(:[]).with("#{folder}/**/*").returns(subfolders) + end + + FileUtils.expects(:rm_rf).never + FileUtils.expects(:rm_rf).with("sbar").once + @instance.clean_machine_folder + end + + should "delete directories with only subdirectories" do + folders = { + "sfoo" => %W[foo bar], + "sbar" => %W[foo.xml-prev] + } + + File.stubs(:file?).returns(false) + Dir.expects(:[]).with(@folder).returns(folders.keys) + folders.each do |folder, subfolders| + File.expects(:directory?).with(folder).returns(true) + Dir.expects(:[]).with("#{folder}/**/*").returns(subfolders) + end + + FileUtils.expects(:rm_rf).never + FileUtils.expects(:rm_rf).with("sfoo").once + FileUtils.expects(:rm_rf).with("sbar").once + + @instance.clean_machine_folder + end + end +end diff --git a/vagrant.gemspec b/vagrant.gemspec index 69be899d4..fd444575e 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= s.authors = ["Mitchell Hashimoto", "John Bender"] - s.date = %q{2010-07-13} + s.date = %q{2010-07-14} s.default_executable = %q{vagrant} s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.} s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"] @@ -47,6 +47,7 @@ Gem::Specification.new do |s| "lib/vagrant/action/exception_catcher.rb", "lib/vagrant/action/vm/boot.rb", "lib/vagrant/action/vm/check_guest_additions.rb", + "lib/vagrant/action/vm/clean_machine_folder.rb", "lib/vagrant/action/vm/clear_forwarded_ports.rb", "lib/vagrant/action/vm/clear_nfs_exports.rb", "lib/vagrant/action/vm/clear_shared_folders.rb", @@ -134,6 +135,7 @@ Gem::Specification.new do |s| "test/vagrant/action/exception_catcher_test.rb", "test/vagrant/action/vm/boot_test.rb", "test/vagrant/action/vm/check_guest_additions_test.rb", + "test/vagrant/action/vm/clean_machine_folder_test.rb", "test/vagrant/action/vm/clear_forwarded_ports_test.rb", "test/vagrant/action/vm/clear_nfs_exports_test.rb", "test/vagrant/action/vm/clear_shared_folders_test.rb", @@ -218,6 +220,7 @@ Gem::Specification.new do |s| "test/vagrant/action/exception_catcher_test.rb", "test/vagrant/action/vm/boot_test.rb", "test/vagrant/action/vm/check_guest_additions_test.rb", + "test/vagrant/action/vm/clean_machine_folder_test.rb", "test/vagrant/action/vm/clear_forwarded_ports_test.rb", "test/vagrant/action/vm/clear_nfs_exports_test.rb", "test/vagrant/action/vm/clear_shared_folders_test.rb",