Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab_settings/options.rb')
-rw-r--r--lib/gitlab_settings/options.rb110
1 files changed, 97 insertions, 13 deletions
diff --git a/lib/gitlab_settings/options.rb b/lib/gitlab_settings/options.rb
index 077c1aa944a..68555794436 100644
--- a/lib/gitlab_settings/options.rb
+++ b/lib/gitlab_settings/options.rb
@@ -1,7 +1,42 @@
# frozen_string_literal: true
+require 'forwardable'
+
module GitlabSettings
class Options
+ extend Forwardable
+
+ def_delegators :@options,
+ :count,
+ :deep_stringify_keys,
+ :deep_symbolize_keys,
+ :default_proc,
+ :dig,
+ :each_key,
+ :each_pair,
+ :each_value,
+ :each,
+ :empty?,
+ :fetch_values,
+ :fetch,
+ :filter,
+ :keys,
+ :length,
+ :map,
+ :member?,
+ :merge,
+ :reject,
+ :select,
+ :size,
+ :slice,
+ :stringify_keys,
+ :symbolize_keys,
+ :transform_keys,
+ :transform_values,
+ :value?,
+ :values_at,
+ :values
+
# Recursively build GitlabSettings::Options
def self.build(obj)
case obj
@@ -26,22 +61,25 @@ module GitlabSettings
@options[key.to_s] = self.class.build(value)
end
- def key?(name)
- @options.key?(name.to_s) || @options.key?(name.to_sym)
+ def key?(key)
+ @options.key?(key.to_s)
end
alias_method :has_key?, :key?
- def to_hash
- @options.deep_transform_values do |option|
- case option
- when self.class
- option.to_hash
- else
- option
- end
- end
+ # Some configurations use the 'default' key, like:
+ # https://gitlab.com/gitlab-org/gitlab/-/blob/c4d5c77c87494bb320fa7fdf19b0e4d7d52af1d1/spec/support/helpers/stub_configuration.rb#L96
+ # But since `default` is also a method in Hash, this can be confusing and
+ # raise an exception instead of returning nil, as expected in some places.
+ # To avoid that, we use #default always as a possible internal key
+ def default
+ @options['default']
+ end
+
+ # For backward compatibility, like:
+ # https://gitlab.com/gitlab-org/gitlab/-/blob/adf67e90428670aaa955731f3bdeafb8b3a874cd/lib/gitlab/database/health_status/indicators/patroni_apdex.rb#L58
+ def with_indifferent_access
+ to_hash.with_indifferent_access
end
- alias_method :to_h, :to_hash
def dup
self.class.build(to_hash)
@@ -51,16 +89,56 @@ module GitlabSettings
self.class.build(to_hash.merge(other.deep_stringify_keys))
end
+ def merge!(other)
+ @options = to_hash.merge(other.deep_stringify_keys)
+ end
+
def deep_merge(other)
self.class.build(to_hash.deep_merge(other.deep_stringify_keys))
end
+ def deep_merge!(other)
+ @options = to_hash.deep_merge(other.deep_stringify_keys)
+ end
+
def is_a?(klass)
return true if klass == Hash
super(klass)
end
+ def to_hash
+ @options.deep_transform_values do |option|
+ case option
+ when self.class
+ option.to_hash
+ else
+ option
+ end
+ end
+ end
+ alias_method :to_h, :to_hash
+
+ # Don't alter the internal keys
+ def stringify_keys!
+ error_msg = "Warning: Do not mutate #{self.class} objects: `#{__method__}`"
+
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(RuntimeError.new(error_msg), method: __method__)
+
+ to_hash.deep_stringify_keys
+ end
+ alias_method :deep_stringify_keys!, :stringify_keys!
+
+ # Don't alter the internal keys
+ def symbolize_keys!
+ error_msg = "Warning: Do not mutate #{self.class} objects: `#{__method__}`"
+
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(RuntimeError.new(error_msg), method: __method__)
+
+ to_hash.deep_symbolize_keys
+ end
+ alias_method :deep_symbolize_keys!, :symbolize_keys!
+
def method_missing(name, *args, &block)
name_string = +name.to_s
@@ -70,7 +148,13 @@ module GitlabSettings
return self[name_string]
end
- return @options.public_send(name, *args, &block) if @options.respond_to?(name) # rubocop: disable GitlabSecurity/PublicSend
+ if @options.respond_to?(name)
+ error_msg = "Calling a hash method on #{self.class}: `#{name}`"
+
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(RuntimeError.new(error_msg), method: name)
+
+ return @options.public_send(name, *args, &block) # rubocop: disable GitlabSecurity/PublicSend
+ end
raise ::GitlabSettings::MissingSetting, "option '#{name}' not defined"
end