lib/pdk/config/namespace.rb in pdk-1.16.0 vs lib/pdk/config/namespace.rb in pdk-1.17.0

- old
+ new

@@ -32,10 +32,11 @@ @name = name.to_s @parent = parent @persistent_defaults = persistent_defaults @mounts = {} @loaded_from_file = false + @read_only = false instance_eval(&block) if block_given? end # Pre-configure a value in the namespace. @@ -46,11 +47,11 @@ # @param key [String,Symbol] the name of the value. # @param block [Proc] a block that is evaluated within the new [self]. # # @return [nil] def setting(key, &block) - @settings[key.to_s] ||= PDK::Config::Setting.new(key.to_s, self) + @settings[key.to_s] ||= default_setting_class.new(key.to_s, self) @settings[key.to_s].instance_eval(&block) if block_given? end # Mount a provided [self] (or subclass) into the namespace. # @@ -95,11 +96,12 @@ # Check if it's a mount first... return @mounts[key.to_s] unless @mounts[key.to_s].nil? # Check if it's a setting, otherwise nil return nil if settings[key.to_s].nil? return settings[key.to_s].value unless settings[key.to_s].value.nil? - default_value = settings[key.to_s].default + # Duplicate arrays and hashes so that they are isolated from changes being made + default_value = PDK::Util.deep_duplicate(settings[key.to_s].default) return default_value if default_value.nil? || !@persistent_defaults # Persist the default value settings[key.to_s].value = default_value save_data default_value @@ -203,12 +205,30 @@ # namespace. def include_in_parent? child_namespace? && file.nil? end + # Disables the namespace, and child namespaces, from writing changes to disk. + # Typically this is only needed for unit testing. + # @api private + def read_only! + @read_only = true + @mounts.each { |_, child| child.read_only! } + end + private + # Returns the object class to create settings with. Subclasses may override this to use specific setting classes + # + # @return [Class[PDK::Config::Setting]] + # + # @abstract + # @private + def default_setting_class + PDK::Config::Setting + end + # Determines whether a setting name should be resolved using the filter # Returns true when filter is nil. # Returns true if the filter is exactly the same name as the setting. # Returns true if the name is a sub-key of the filter e.g. # Given a filter of user.module_defaults, `user.module_defaults.author` will return true, but `user.analytics.disabled` will return false. @@ -251,11 +271,11 @@ # writing to disk. def create_missing_setting(key, initial_value = nil) # Need to use `@settings` and `@mounts` here to stop recursive calls return unless @mounts[key.to_s].nil? return unless @settings[key.to_s].nil? - @settings[key.to_s] = PDK::Config::Setting.new(key.to_s, self, initial_value) + @settings[key.to_s] = default_setting_class.new(key.to_s, self, initial_value) end # Set the value of the named key. # # If the key has been pre-configured with {#value}, then the value of the @@ -279,11 +299,11 @@ # not exist. def load_data(filename) return if filename.nil? return unless PDK::Util::Filesystem.file?(filename) - PDK::Util::Filesystem.read_file(file) + PDK::Util::Filesystem.read_file(filename) rescue Errno::ENOENT => e raise PDK::Config::LoadError, e.message rescue Errno::EACCES raise PDK::Config::LoadError, _('Unable to open %{file} for reading') % { file: filename, @@ -300,10 +320,10 @@ # @raise [PDK::Config::LoadError] if the user does not have the # permissions needed to write the file. # # @return [nil] def save_data - return if file.nil? + return if file.nil? || @read_only PDK::Util::Filesystem.mkdir_p(File.dirname(file)) PDK::Util::Filesystem.write_file(file, serialize_data(to_h)) rescue Errno::EACCES