class Overcommit::Configuration
Stores configuration for Overcommit
and the hooks it runs.
Attributes
Public Class Methods
Creates a configuration from the given hash.
@param hash [Hash] loaded YAML config file as a hash @param options [Hash] @option default [Boolean] whether this is the default built-in configuration @option logger [Overcommit::Logger]
# File lib/overcommit/configuration.rb, line 15 def initialize(hash, options = {}) @options = options.dup @options[:logger] ||= Overcommit::Logger.silent @hash = hash # Assign so validator can read original values unless options[:validate] == false @hash = Overcommit::ConfigurationValidator.new.validate(self, hash, options) end end
Public Instance Methods
# File lib/overcommit/configuration.rb, line 24 def ==(other) super || @hash == other.hash end
Access the configuration as if it were a hash.
@param key [String] @return [Array,Hash,Number,String]
# File lib/overcommit/configuration.rb, line 32 def [](key) @hash[key] end
Returns configuration for all built-in hooks in each hook type.
@return [Hash]
# File lib/overcommit/configuration.rb, line 72 def all_builtin_hook_configs hook_configs = {} Overcommit::Utils.supported_hook_type_classes.each do |hook_type| hook_names = @hash[hook_type].keys.reject { |name| name == 'ALL' } hook_configs[hook_type] = Hash[ hook_names.map do |hook_name| [hook_name, for_hook(hook_name, hook_type)] end ] end hook_configs end
Returns configuration for all hooks in each hook type.
@return [Hash]
# File lib/overcommit/configuration.rb, line 65 def all_hook_configs smart_merge(all_builtin_hook_configs, all_plugin_hook_configs) end
Returns configuration for all plugin hooks in each hook type.
@return [Hash]
# File lib/overcommit/configuration.rb, line 91 def all_plugin_hook_configs hook_configs = {} Overcommit::Utils.supported_hook_types.each do |hook_type| hook_type_class_name = Overcommit::Utils.camel_case(hook_type) directory = File.join(plugin_directory, hook_type.tr('-', '_')) plugin_paths = Dir[File.join(directory, '*.rb')].sort hook_names = plugin_paths.map do |path| Overcommit::Utils.camel_case(File.basename(path, '.rb')) end hook_configs[hook_type_class_name] = Hash[ hook_names.map do |hook_name| [hook_name, for_hook(hook_name, Overcommit::Utils.camel_case(hook_type))] end ] end hook_configs end
Applies additional configuration settings based on the provided environment variables.
# File lib/overcommit/configuration.rb, line 157 def apply_environment!(hook_context, env) skipped_hooks = "#{env['SKIP']} #{env['SKIP_CHECKS']} #{env['SKIP_HOOKS']}".split(/[:, ]/) only_hooks = env.fetch('ONLY') { '' }.split(/[:, ]/) hook_type = hook_context.hook_class_name if only_hooks.any? || skipped_hooks.include?('all') || skipped_hooks.include?('ALL') @hash[hook_type]['ALL']['skip'] = true end only_hooks.select { |hook_name| hook_exists?(hook_context, hook_name) }. map { |hook_name| Overcommit::Utils.camel_case(hook_name) }. each do |hook_name| @hash[hook_type][hook_name] ||= {} @hash[hook_type][hook_name]['skip'] = false end skipped_hooks.select { |hook_name| hook_exists?(hook_context, hook_name) }. map { |hook_name| Overcommit::Utils.camel_case(hook_name) }. each do |hook_name| @hash[hook_type][hook_name] ||= {} @hash[hook_type][hook_name]['skip'] = true end end
# File lib/overcommit/configuration.rb, line 42 def concurrency @concurrency ||= begin cores = Overcommit::Utils.processor_count content = @hash.fetch('concurrency') { '%<processors>d' } if content.is_a?(String) concurrency_expr = content % { processors: cores } a, op, b = concurrency_expr.scan(%r{(\d+)\s*([+\-*\/])\s*(\d+)})[0] if a a.to_i.send(op, b.to_i) else concurrency_expr.to_i end else content.to_i end end end
Returns the ad hoc hooks that have been enabled for a hook type.
# File lib/overcommit/configuration.rb, line 123 def enabled_ad_hoc_hooks(hook_context) @hash[hook_context.hook_class_name].keys. reject { |hook_name| hook_name == 'ALL' }. select { |hook_name| ad_hoc_hook?(hook_context, hook_name) }. select { |hook_name| hook_enabled?(hook_context, hook_name) } end
Returns the built-in hooks that have been enabled for a hook type.
# File lib/overcommit/configuration.rb, line 115 def enabled_builtin_hooks(hook_context) @hash[hook_context.hook_class_name].keys. reject { |hook_name| hook_name == 'ALL' }. select { |hook_name| built_in_hook?(hook_context, hook_name) }. select { |hook_name| hook_enabled?(hook_context, hook_name) } end
Returns a non-modifiable configuration for a hook.
# File lib/overcommit/configuration.rb, line 131 def for_hook(hook, hook_type = nil) unless hook_type components = hook.class.name.split('::') hook = components.last hook_type = components[-2] end # Merge hook configuration with special 'ALL' config hook_config = smart_merge(@hash[hook_type]['ALL'], @hash[hook_type][hook] || {}) # Need to specially handle `enabled` option since not setting it does not # necessarily mean the hook is disabled hook_config['enabled'] = hook_enabled?(hook_type, hook) hook_config.freeze end
Merges the given configuration with this one, returning a new {Configuration}. The provided configuration will either add to or replace any options defined in this configuration.
# File lib/overcommit/configuration.rb, line 151 def merge(config) self.class.new(smart_merge(@hash, config.hash)) end
Returns absolute path to the directory that external hook plugins should be loaded from.
# File lib/overcommit/configuration.rb, line 38 def plugin_directory File.join(Overcommit::Utils.repo_root, @hash['plugin_directory'] || '.git-hooks') end
# File lib/overcommit/configuration.rb, line 181 def plugin_hook?(hook_context_or_type, hook_name) hook_type_name = if hook_context_or_type.is_a?(String) Overcommit::Utils.snake_case(hook_context_or_type) else hook_context_or_type.hook_type_name end hook_name = Overcommit::Utils.snake_case(hook_name) File.exist?(File.join(plugin_directory, hook_type_name, "#{hook_name}.rb")) end
Return whether a previous signature has been recorded for this configuration.
@return [true,false]
# File lib/overcommit/configuration.rb, line 205 def previous_signature? !stored_signature.empty? end
Return whether the signature for this configuration has changed since it was last calculated.
@return [true,false]
# File lib/overcommit/configuration.rb, line 197 def signature_changed? signature != stored_signature end
Update the currently stored signature for this hook.
# File lib/overcommit/configuration.rb, line 234 def update_signature! result = Overcommit::Utils.execute( %w[git config --local] + [signature_config_key, signature] ) verify_signature_value = @hash['verify_signatures'] ? 1 : 0 result &&= Overcommit::Utils.execute( %W[git config --local #{verify_signature_config_key} #{verify_signature_value}] ) unless result.success? raise Overcommit::Exceptions::GitConfigError, "Unable to write to local repo git config: #{result.stderr}" end end
Returns whether this configuration should verify itself by checking the stored configuration for the repo.
@return [true,false]
# File lib/overcommit/configuration.rb, line 213 def verify_signatures? return false if ENV['OVERCOMMIT_NO_VERIFY'] return true if @hash['verify_signatures'] != false result = Overcommit::Utils.execute( %W[git config --local --get #{verify_signature_config_key}] ) if result.status == 1 # Key doesn't exist return true elsif result.status != 0 raise Overcommit::Exceptions::GitConfigError, "Unable to read from local repo git config: #{result.stderr}" end # We don't cast since we want to allow anything to count as "true" except # a literal zero result.stdout.strip != '0' end
Private Instance Methods
# File lib/overcommit/configuration.rb, line 256 def ad_hoc_hook?(hook_context, hook_name) ad_hoc_conf = @hash.fetch(hook_context.hook_class_name) { {} }.fetch(hook_name) { {} } # Ad hoc hooks are neither built-in nor have a plugin file written but # still have a `command` specified to be run !built_in_hook?(hook_context, hook_name) && !plugin_hook?(hook_context, hook_name) && (ad_hoc_conf['command'] || ad_hoc_conf['required_executable']) end
# File lib/overcommit/configuration.rb, line 266 def built_in_hook?(hook_context, hook_name) hook_name = Overcommit::Utils.snake_case(hook_name) File.exist?(File.join(Overcommit::HOME, 'lib', 'overcommit', 'hook', hook_context.hook_type_name, "#{hook_name}.rb")) end
# File lib/overcommit/configuration.rb, line 279 def hook_enabled?(hook_context_or_type, hook_name) hook_type = if hook_context_or_type.is_a?(String) hook_context_or_type else hook_context_or_type.hook_class_name end individual_enabled = @hash[hook_type].fetch(hook_name) { {} }['enabled'] return individual_enabled unless individual_enabled.nil? all_enabled = @hash[hook_type]['ALL']['enabled'] return all_enabled unless all_enabled.nil? false end
# File lib/overcommit/configuration.rb, line 273 def hook_exists?(hook_context, hook_name) built_in_hook?(hook_context, hook_name) || plugin_hook?(hook_context, hook_name) || ad_hoc_hook?(hook_context, hook_name) end
Returns the unique signature of this configuration.
@return [String]
# File lib/overcommit/configuration.rb, line 317 def signature Digest::SHA256.hexdigest(@hash.to_json) end
# File lib/overcommit/configuration.rb, line 342 def signature_config_key 'overcommit.configuration.signature' end
# File lib/overcommit/configuration.rb, line 296 def smart_merge(parent, child) # Treat the ALL hook specially so that it overrides any configuration # specified by the default configuration. child_all = child['ALL'] unless child_all.nil? parent = Hash[parent.collect { |k, v| [k, smart_merge(v, child_all)] }] end parent.merge(child) do |_key, old, new| case old when Hash smart_merge(old, new) else new end end end
Returns the stored signature of this repo’s Overcommit
configuration.
This is intended to be compared against the current signature of this configuration object.
@return [String]
# File lib/overcommit/configuration.rb, line 327 def stored_signature result = Overcommit::Utils.execute( %w[git config --local --get] + [signature_config_key] ) if result.status == 1 # Key doesn't exist return '' elsif result.status != 0 raise Overcommit::Exceptions::GitConfigError, "Unable to read from local repo git config: #{result.stderr}" end result.stdout.chomp end
# File lib/overcommit/configuration.rb, line 346 def verify_signature_config_key 'overcommit.configuration.verifysignatures' end