diff --git a/lib/vagrant.rb b/lib/vagrant.rb index 958992cc6..ea2268090 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -8,11 +8,13 @@ module Vagrant # TODO: Move more classes over to the autoload model. We'll # start small, but slowly move everything over. - autoload :CLI, 'vagrant/cli' - autoload :Config, 'vagrant/config' - autoload :DataStore, 'vagrant/data_store' - autoload :Errors, 'vagrant/errors' - autoload :Util, 'vagrant/util' + autoload :Box, 'vagrant/box' + autoload :BoxCollection, 'vagrant/box_collection' + autoload :CLI, 'vagrant/cli' + autoload :Config, 'vagrant/config' + autoload :DataStore, 'vagrant/data_store' + autoload :Errors, 'vagrant/errors' + autoload :Util, 'vagrant/util' module Command autoload :Base, 'vagrant/command/base' diff --git a/lib/vagrant/box_collection.rb b/lib/vagrant/box_collection.rb new file mode 100644 index 000000000..2bd646eb7 --- /dev/null +++ b/lib/vagrant/box_collection.rb @@ -0,0 +1,38 @@ +module Vagrant + # Represents a collection of boxes, providing helpful methods for + # finding boxes. + class BoxCollection < Array + attr_reader :env + + def initialize(env) + super() + + @env = env + reload! + end + + # Find a box in the collection by the given name. The name must + # be a string, for now. + def find(name) + each do |box| + return box if box.name == name + end + + nil + end + + # Loads the list of all boxes from the source. This modifies the + # current array. + def reload! + clear + + Dir.open(env.boxes_path) do |dir| + dir.each do |d| + next if d == "." || d == ".." || !File.directory?(env.boxes_path.join(d)) + self << Box.new(env, d) + end + end + end + end +end + diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 0c2c05a77..28f6b8d02 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -13,7 +13,6 @@ module Vagrant attr_reader :parent # Parent environment (in the case of multi-VMs) attr_reader :cwd - attr_reader :box attr_accessor :vm attr_writer :ui @@ -81,6 +80,17 @@ module Vagrant vm.name rescue "vagrant" end + # Returns the collection of boxes for the environment. + def boxes + return parent.boxes if parent + @_boxes ||= BoxCollection.new(self) + end + + # Returns the box that this environment represents. + def box + boxes.find(config.vm.box) + end + # Returns the VMs associated with this environment. def vms return parent.vms if parent @@ -252,7 +262,6 @@ module Vagrant # After the first run we want to load the configuration again since # it can change due to box Vagrantfiles and home directory Vagrantfiles load_home_directory! - load_box! load_config! end end @@ -273,11 +282,6 @@ module Vagrant end end - # Loads the specified box for this environment. - def load_box! - @box = Box.find(self, config.vm.box) if config.vm.box - end - # Loads the persisted VM (if it exists) for this environment. def load_vm! # This environment represents a single sub VM. The VM is then diff --git a/test/support/path.rb b/test/support/path.rb index fa666d896..a84170456 100644 --- a/test/support/path.rb +++ b/test/support/path.rb @@ -26,7 +26,11 @@ module VagrantTestHelpers # Cleans all the test temp paths def clean_paths FileUtils.rm_rf(tmp_path) - FileUtils.mkdir_p(tmp_path) + + # Call these methods only to rebuild the directories + tmp_path + home_path + boxes_path end end end diff --git a/test/vagrant/box_collection_test.rb b/test/vagrant/box_collection_test.rb new file mode 100644 index 000000000..67a9338ba --- /dev/null +++ b/test/vagrant/box_collection_test.rb @@ -0,0 +1,44 @@ +require "test_helper" + +class BoxCollectionTest < Test::Unit::TestCase + setup do + clean_paths + + @klass = Vagrant::BoxCollection + end + + should "load all the boxes from the box path" do + vagrant_box("foo") + vagrant_box("bar") + + result = @klass.new(vagrant_env) + names = result.collect { |b| b.name }.sort + assert_equal 2, result.length + assert_equal ["bar", "foo"], names + end + + should "reload the box list" do + instance = @klass.new(vagrant_env) + assert instance.empty? + + vagrant_box("foo") + + instance.reload! + assert !instance.empty? + end + + should "find a specific box" do + vagrant_box("foo") + vagrant_box("bar") + + instance = @klass.new(vagrant_env) + result = instance.find("foo") + assert result + assert_equal "foo", result.name + end + + should "return nil if it couldn't find a specific box" do + instance = @klass.new(vagrant_env) + assert_nil instance.find("thisshouldnotexist") + end +end diff --git a/test/vagrant/environment_test.rb b/test/vagrant/environment_test.rb index ddd75573a..4797a921f 100644 --- a/test/vagrant/environment_test.rb +++ b/test/vagrant/environment_test.rb @@ -285,6 +285,41 @@ class EnvironmentTest < Test::Unit::TestCase end end + context "accessing the box collection" do + should "create a box collection representing the environment" do + env = vagrant_env + assert env.boxes.is_a?(Vagrant::BoxCollection) + assert_equal env, env.boxes.env + end + + should "not load the environment if its already loaded" do + env = vagrant_env + env.expects(:load!).never + env.boxes + end + + should "return the parent's box collection if it has one" do + env = vagrant_env(vagrantfile(<<-vf)) + config.vm.define :web + config.vm.define :db + vf + + assert env.vms[:web].env.boxes.equal?(env.boxes) + end + end + + context "accessing the current box" do + should "return the box that is specified in the config" do + vagrant_box("foo") + env = vagrant_env(vagrantfile(<<-vf)) + config.vm.box = "foo" + vf + + assert env.box + assert_equal "foo", env.box.name + end + end + context "accessing the VMs hash" do should "load the environment if its not already loaded" do env = @klass.new(:cwd => vagrantfile) @@ -405,25 +440,6 @@ class EnvironmentTest < Test::Unit::TestCase end end - context "loading box" do - should "not load the box if its not set" do - env = vagrant_env - assert env.config.vm.box.nil? - Vagrant::Box.expects(:find).never - env.load_box! - end - - should "set the box to what is found by the Box class" do - env = vagrant_env(vagrantfile("config.vm.box = 'foo'")) - - @box = mock("box") - @box.stubs(:env=) - Vagrant::Box.expects(:find).with(env, env.config.vm.box).once.returns(@box) - env.load_box! - assert @box.equal?(env.box) - end - end - context "loading the UUID out from the persisted dotfile" do setup do @env = vagrant_env