Run each config proc only once

This commit is contained in:
Mitchell Hashimoto 2012-01-11 20:59:21 -08:00
parent 7c9c6e34ce
commit 008132b3cb
3 changed files with 47 additions and 19 deletions

View File

@ -25,6 +25,20 @@ module Vagrant
end end
end end
# Merge another configuration object into this one.
#
# @param [Object] other The other configuration object to merge from,
# this must be the same type of object as this one.
# @return [Object] The merged object.
def merge(other)
result = self.class.new
instance_variables_hash.merge(other.instance_variables_hash).each do |key, value|
result.instance_variable_set("@#{key}".to_sym, value)
end
result
end
# Called by {Top} after the configuration is loaded to validate # Called by {Top} after the configuration is loaded to validate
# the configuaration objects. Subclasses should implement this # the configuaration objects. Subclasses should implement this
# method and add any errors to the `errors` object given. # method and add any errors to the `errors` object given.
@ -54,7 +68,7 @@ module Vagrant
# Returns the instance variables as a hash of key-value pairs. # Returns the instance variables as a hash of key-value pairs.
def instance_variables_hash def instance_variables_hash
instance_variables.inject({}) do |acc, iv| instance_variables.inject({}) do |acc, iv|
acc[iv.to_s[1..-1]] = instance_variable_get(iv) unless iv.to_sym == :@top acc[iv.to_s[1..-1]] = instance_variable_get(iv)
acc acc
end end
end end

View File

@ -20,6 +20,7 @@ module Vagrant
@logger = Log4r::Logger.new("vagrant::config::loader") @logger = Log4r::Logger.new("vagrant::config::loader")
@sources = {} @sources = {}
@proc_cache = {} @proc_cache = {}
@config_cache = {}
end end
# Set the configuration data for the given name. # Set the configuration data for the given name.
@ -70,21 +71,26 @@ module Vagrant
end end
# Create the top-level configuration which will hold all the config. # Create the top-level configuration which will hold all the config.
top = Top.new result = Top.new
@load_order.each do |key| @load_order.each do |key|
next if !@sources.has_key?(key) next if !@sources.has_key?(key)
@sources[key].each do |proc| @sources[key].each do |proc|
@logger.debug("Loading from: #{key}") if !@config_cache.has_key?(proc)
@logger.debug("Loading from: #{key} (evaluating)")
current = Top.new
proc.call(current)
@config_cache[proc] = current
end
# Call each proc with the top-level configuration. # Merge in the results of this proc's configuration
proc.call(top) result = result.merge(@config_cache[proc])
end end
end end
@logger.debug("Configuration loaded successfully") @logger.debug("Configuration loaded successfully")
top result
end end
protected protected

View File

@ -22,6 +22,27 @@ describe Vagrant::Config::Loader do
config.vagrant.dotfile_name.should == "foo" config.vagrant.dotfile_name.should == "foo"
end end
it "should only run the same proc once" do
count = 0
proc = Proc.new do |config|
config.vagrant.dotfile_name = "foo"
count += 1
end
instance.load_order = [:proc]
instance.set(:proc, proc)
5.times do
result = instance.load
# Verify the config result
result.vagrant.dotfile_name.should == "foo"
# Verify the count is only one
count.should == 1
end
end
it "should only load configuration files once" do it "should only load configuration files once" do
$_config_data = 0 $_config_data = 0
@ -35,19 +56,6 @@ describe Vagrant::Config::Loader do
$_config_data.should == 1 $_config_data.should == 1
end end
it "should clear cache on setting to a new value" do
$_config_data = 0
instance.load_order = [:proc]
instance.set(:proc, temporary_file("$_config_data += 1"))
5.times { instance.load }
instance.set(:proc, temporary_file("$_config_data += 1"))
5.times { instance.load }
$_config_data.should == 2
end
it "should not clear the cache if setting to the same value multiple times" do it "should not clear the cache if setting to the same value multiple times" do
$_config_data = 0 $_config_data = 0