diff --git a/lib/vagrant/box_collection2.rb b/lib/vagrant/box_collection2.rb index 64ab80ea4..88fa015a6 100644 --- a/lib/vagrant/box_collection2.rb +++ b/lib/vagrant/box_collection2.rb @@ -1,3 +1,5 @@ +require "log4r" + module Vagrant # Represents a collection a boxes found on disk. This provides methods # for accessing/finding individual boxes, adding new boxes, or deleting @@ -12,6 +14,46 @@ module Vagrant # of boxes. def initialize(directory) @directory = directory + @logger = Log4r::Logger.new("vagrant::box_collection") + end + + # This returns an array of all the boxes on the system, given by + # their name and their provider. + # + # @return [Array] Array of `[name, provider]` pairs of the boxes + # installed on this system. An optional third element in the array + # may specify `:v1` if the box is a version 1 box. + def all + results = [] + + @logger.debug("Finding all boxes in: #{@directory}") + @directory.children(true).each do |child| + box_name = child.basename.to_s + + # If this is a V1 box, we still return that name, but specify + # that the box is a V1 box. + if v1_box?(child) + @logger.debug("V1 box found: #{box_name}") + results << [box_name, :virtualbox, :v1] + next + end + + # Otherwise, traverse the subdirectories and see what providers + # we have. + child.children(true).each do |provider| + # Verify this is a potentially valid box. If it looks + # correct enough then include it. + if provider.directory? && provider.join("metadata.json").file? + provider_name = provider.basename.to_s.to_sym + @logger.debug("Box: #{box_name} (#{provider_name})") + results << [box_name, provider_name] + else + @logger.debug("Invalid box, ignoring: #{provider}") + end + end + end + + results end # Find a box in the collection with the given name and provider. @@ -22,7 +64,11 @@ module Vagrant def find(name, provider) # First look directly for the box we're asking for. box_directory = @directory.join(name, provider.to_s, "metadata.json") - return Box2.new(name, provider, box_directory.dirname) if box_directory.file? + @logger.info("Searching for box: #{name} (#{provider}) in #{box_directory}") + if box_directory.file? + @logger.debug("Box found: #{name} (#{provider})") + return Box2.new(name, provider, box_directory.dirname) + end # Check if a V1 version of this box exists, and if so, raise an # exception notifying the caller that the box exists but needs @@ -32,12 +78,26 @@ module Vagrant # # To determine if it is a V1 box we just do a simple heuristic # based approach. - if @directory.join(name, "box.ovf").file? + @logger.info("Searching for V1 box: #{name}") + if v1_box?(name) + @logger.warn("V1 box found: #{name}") raise Errors::BoxUpgradeRequired, :name => name end # Didn't find it, return nil + @logger.info("Box not found: #{name} (#{provider})") nil end + + protected + + # This checks if the given name represents a V1 box on the system. + # + # @return [Boolean] + def v1_box?(name) + # We detect a V1 box given by whether there is a "box.ovf" which + # is a heuristic but is pretty accurate. + @directory.join(name, "box.ovf").file? + end end end diff --git a/test/unit/support/isolated_environment.rb b/test/unit/support/isolated_environment.rb index 66fb693cf..16b8a45d8 100644 --- a/test/unit/support/isolated_environment.rb +++ b/test/unit/support/isolated_environment.rb @@ -32,12 +32,24 @@ module Unit end def box(name, vagrantfile_contents="") + # Create the box directory box_dir = boxes_dir.join(name) box_dir.mkpath + + # Create the "box.ovf" file because that is how Vagrant heuristically + # determines a box is a V1 box. + box_dir.join("box.ovf").open("w") { |f| f.write("") } + + # Populate the vagrantfile vagrantfile(vagrantfile_contents, box_dir) + + # Return the directory box_dir end + # Create an alias because "box" makes a V1 box, so "box1" + alias :box1 :box + # Creates a fake box to exist in this environment. # # @param [String] name Name of the box diff --git a/test/unit/vagrant/box_collection2_test.rb b/test/unit/vagrant/box_collection2_test.rb index 7404525d8..8715efda1 100644 --- a/test/unit/vagrant/box_collection2_test.rb +++ b/test/unit/vagrant/box_collection2_test.rb @@ -9,6 +9,34 @@ describe Vagrant::BoxCollection2 do let(:environment) { isolated_environment } let(:instance) { described_class.new(environment.boxes_dir) } + describe "listing all" do + it "should return an empty array when no boxes are there" do + instance.all.should == [] + end + + it "should return the boxes and their providers" do + # Create some boxes + environment.box2("foo", :virtualbox) + environment.box2("foo", :vmware) + environment.box2("bar", :ec2) + + # Verify some output + results = instance.all.sort + results.length.should == 3 + results.should == [["foo", :virtualbox], ["foo", :vmware], ["bar", :ec2]].sort + end + + it "should return V1 boxes as well" do + # Create some boxes, including a V1 box + environment.box1("bar") + environment.box2("foo", :vmware) + + # Verify some output + results = instance.all.sort + results.should == [["bar", :virtualbox, :v1], ["foo", :vmware]] + end + end + describe "finding" do it "should return nil if the box does not exist" do instance.find("foo", :i_dont_exist).should be_nil