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
# 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
# the configuaration objects. Subclasses should implement this
# 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.
def instance_variables_hash
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
end
end

View File

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

View File

@ -22,6 +22,27 @@ describe Vagrant::Config::Loader do
config.vagrant.dotfile_name.should == "foo"
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
$_config_data = 0
@ -35,19 +56,6 @@ describe Vagrant::Config::Loader do
$_config_data.should == 1
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
$_config_data = 0