diff --git a/lib/vagrant/guest.rb b/lib/vagrant/guest.rb index 52dcd3e21..2a36ea3e6 100644 --- a/lib/vagrant/guest.rb +++ b/lib/vagrant/guest.rb @@ -19,11 +19,19 @@ module Vagrant class Guest attr_reader :chain - def initialize(machine, guests) - @logger = Log4r::Logger.new("vagrant::guest") - @chain = [] - @guests = guests - @machine = machine + # The name of the guest OS. This is available after {#detect!} is + # called. + # + # @return [Symbol] + attr_reader :name + + def initialize(machine, guests, capabilities) + @logger = Log4r::Logger.new("vagrant::guest") + @capabilities = capabilities + @chain = [] + @guests = guests + @machine = machine + @name = nil end # This will detect the proper guest OS for the machine and set up @@ -63,15 +71,18 @@ module Vagrant if guest.detect?(@machine) @logger.info("Detected: #{name}!") - @chain << guest + @chain << [name, guest] + @name = name # Build the proper chain of parents if there are any. # This allows us to do "inheritence" of capabilities later if guest_info[1] - parent_info = @guests[guest_info[1]] + parent_name = guest_info[1] + parent_info = @guests[parent_name] while parent_info - @chain << parent_info[0].new - parent_info = @guests[parent_info[1]] + @chain << [parent_name, parent_info[0].new] + parent_name = parent_info[1] + parent_info = @guests[parent_name] end end @@ -89,6 +100,18 @@ module Vagrant raise Errors::GuestNotDetected if @chain.empty? end + # Tests whether the guest has the named capability. + # + # @return [Boolean] + def capability?(cap_name) + @chain.each do |guest_name, guest| + caps = @capabilities[guest_name] + return true if caps && caps.has_key?(cap_name) + end + + false + end + # This returns whether the guest is ready to work. If this returns # `false`, then {#detect!} should be called in order to detect the # guest OS. diff --git a/test/unit/vagrant/guest_test.rb b/test/unit/vagrant/guest_test.rb index 0cff98738..228c19360 100644 --- a/test/unit/vagrant/guest_test.rb +++ b/test/unit/vagrant/guest_test.rb @@ -5,10 +5,22 @@ require File.expand_path("../../base", __FILE__) describe Vagrant::Guest do include_context "unit" + let(:capabilities) { {} } let(:guests) { {} } let(:machine) { double("machine") } - subject { described_class.new(machine, guests) } + subject { described_class.new(machine, guests, capabilities) } + + # This registers a capability with a specific guest + def register_capability(guest, capability) + cap = Class.new do + define_method(capability) do + end + end + + capabilities[guest] ||= {} + capabilities[guest][capability] = cap.new + end # This registers a guest with the class. # @@ -29,6 +41,37 @@ describe Vagrant::Guest do guests[name] = [guest, parent] end + describe "#capability?" do + before :each do + register_guest(:foo, nil, true) + register_guest(:bar, :foo, true) + + subject.detect! + end + + it "doesn't have unknown capabilities" do + subject.capability?(:what_is_this_i_dont_even).should_not be + end + + it "doesn't have capabilities registered to other guests" do + register_capability(:baz, :test) + + subject.capability?(:test).should_not be + end + + it "has capability of detected guest" do + register_capability(:bar, :test) + + subject.capability?(:test).should be + end + + it "has capability of parent guests" do + register_capability(:foo, :test) + + subject.capability?(:test).should be + end + end + describe "#detect!" do it "detects the first match" do register_guest(:foo, nil, false) @@ -36,8 +79,10 @@ describe Vagrant::Guest do register_guest(:baz, nil, false) subject.detect! + subject.name.should == :bar subject.chain.length.should == 1 - subject.chain[0].name.should == :bar + subject.chain[0][0].should == :bar + subject.chain[0][1].name.should == :bar end it "detects those with the most parents first" do @@ -48,8 +93,10 @@ describe Vagrant::Guest do register_guest(:bar2, :foo2, true) subject.detect! + subject.name.should == :baz subject.chain.length.should == 3 - subject.chain.map(&:name).should == [:baz, :bar, :foo] + subject.chain.map(&:first).should == [:baz, :bar, :foo] + subject.chain.map { |x| x[1] }.map(&:name).should == [:baz, :bar, :foo] end it "raises an exception if no guest can be detected" do