diff --git a/lib/vagrant/config.rb b/lib/vagrant/config.rb index d77fa22eb..a6aef45aa 100644 --- a/lib/vagrant/config.rb +++ b/lib/vagrant/config.rb @@ -1,15 +1,31 @@ +require "vagrant/registry" + module Vagrant module Config autoload :Base, 'vagrant/config/base' autoload :Container, 'vagrant/config/container' autoload :ErrorRecorder, 'vagrant/config/error_recorder' autoload :Loader, 'vagrant/config/loader' - autoload :Top, 'vagrant/config/top' + autoload :VersionBase, 'vagrant/config/version_base' autoload :V1, 'vagrant/config/v1' + # This is a mutex used to guarantee that only one thread can load + # procs at any given time. CONFIGURE_MUTEX = Mutex.new + # This is the registry which keeps track of what configuration + # versions are available, mapped by the version string used in + # `Vagrant.configure` calls. + VERSIONS = Registry.new + VERSIONS.register("1") { V1 } + + # This is the order of versions. This is used by the loader to figure out + # how to "upgrade" versions up to the desired (current) version. The + # current version is always considered to be the last version in this + # list. + VERSIONS_ORDER = ["1"] + # This is the method which is called by all Vagrantfiles to configure Vagrant. # This method expects a block which accepts a single argument representing # an instance of the {Config::Top} class. diff --git a/lib/vagrant/config/loader.rb b/lib/vagrant/config/loader.rb index 0891e30aa..e2df7ef04 100644 --- a/lib/vagrant/config/loader.rb +++ b/lib/vagrant/config/loader.rb @@ -70,8 +70,12 @@ module Vagrant @logger.error("Unknown config sources: #{unknown_sources.inspect}") end + # Get the current version config class to use + current_version = Config::VERSIONS_ORDER.last + current_config_klass = Config::VERSIONS.get(current_version) + # This will hold our result - result = V1.init + result = current_config_klass.init @load_order.each do |key| next if !@sources.has_key?(key) @@ -79,14 +83,14 @@ module Vagrant @sources[key].each do |proc| if !@config_cache.has_key?(proc) @logger.debug("Loading from: #{key} (evaluating)") - current = V1.load(proc) + current = current_config_klass.load(proc) @config_cache[proc] = current else @logger.debug("Loading from: #{key} (cache)") end # Merge the configurations - result = V1.merge(result, @config_cache[proc]) + result = current_config_klass.merge(result, @config_cache[proc]) end end diff --git a/lib/vagrant/config/v1.rb b/lib/vagrant/config/v1.rb index 71bcf7d51..68616835e 100644 --- a/lib/vagrant/config/v1.rb +++ b/lib/vagrant/config/v1.rb @@ -1,10 +1,11 @@ +require "vagrant/config/version_base" require "vagrant/config/v1/base" require "vagrant/config/v1/root" module Vagrant module Config # This is the "version 1" configuration loader. - class V1 + class V1 < VersionBase # Returns a bare empty configuration object. # # @return [V1::Root] diff --git a/lib/vagrant/config/v1/base.rb b/lib/vagrant/config/v1/base.rb index 228e4223f..0a05459df 100644 --- a/lib/vagrant/config/v1/base.rb +++ b/lib/vagrant/config/v1/base.rb @@ -1,6 +1,6 @@ module Vagrant module Config - class V1 + class V1 < VersionBase # Base class for configuration keys. It is not required to inherit # from this class but this class provides useful helpers that config # classes may wish to use. diff --git a/lib/vagrant/config/v1/root.rb b/lib/vagrant/config/v1/root.rb index 809851951..26038e2d6 100644 --- a/lib/vagrant/config/v1/root.rb +++ b/lib/vagrant/config/v1/root.rb @@ -1,6 +1,6 @@ module Vagrant module Config - class V1 + class V1 < VersionBase # This is the root configuration class. An instance of this is what # is passed into version 1 Vagrant configuration blocks. class Root diff --git a/lib/vagrant/config/version_base.rb b/lib/vagrant/config/version_base.rb new file mode 100644 index 000000000..647ef8ecf --- /dev/null +++ b/lib/vagrant/config/version_base.rb @@ -0,0 +1,45 @@ +module Vagrant + module Config + # This is the base class for any configuration versions, and includes + # the stub methods that configuaration versions must implement. Vagrant + # supports configuration versioning so that backwards compatibility can be + # maintained for past Vagrantfiles while newer configurations are added. + # Vagrant only introduces new configuration versions for major versions + # of Vagrant. + class VersionBase + # Returns an empty configuration object. This can be any kind of object, + # since it is treated as an opaque value on the other side, used only + # for things like calling into {merge}. + # + # @return [Object] + def self.init + raise NotImplementedError + end + + # Loads the configuration for the given proc and returns a configuration + # object. The return value is treated as an opaque object, so it can be + # anything you'd like. The return value is the object that is passed + # into methods like {merge}, so it should be something you expect. + # + # @param [Proc] proc The proc that is to be configured. + # @return [Object] + def self.load(proc) + raise NotImplementedError + end + + # Merges two configuration objects, returning the merged object. + # The values of `old` and `new` are the opaque objects returned by + # {load} or {init}. + # + # Once again, the return object is treated as an opaque value by + # the Vagrant configuration loader, so it can be anything you'd like. + # + # @param [Object] old Old configuration object. + # @param [Object] new New configuration object. + # @return [Object] The merged configuration object. + def self.merge(old, new) + raise NotImplementedError + end + end + end +end