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