overcommit 0.75.0 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 825a9ffd0ad7bacf35ecb3901ead1f1249085cad5536314434e89ce5ff802d15
4
- data.tar.gz: f4d3ea4ecbc7d2fe7d2c35e1dd4d44f86e30a2e31ba241366735937952a95c30
3
+ metadata.gz: b471934e19dc5c5c31b3ec1b5ed3dccebb4b54990cd3612890623310151fc189
4
+ data.tar.gz: 054c6937dc7c9dde353d2be3f6f03e4ad38bee29f2c348b4299a1ed2e004f36e
5
5
  SHA512:
6
- metadata.gz: 590bcf4bdb5bb506425bbc41050adaa16311baa45f37071d1ffc0a9d96412f508f552eeea2278946bbab622af3aa0a6d216d388c520e41804a4f4dc7ee69e381
7
- data.tar.gz: 73222064a9fcc44930ae9c027c19bb851004d5d1000303854b52c2650ef52ef29177f783e9faa5e064717be3ea03e676512a1dd631ddf68f459acbeb46e08df4
6
+ metadata.gz: 7b32d40b8a2cb773a9bfb7007f67b50c93de5669c5d27df4ea2bfe1e45bd8a771313e3ec8ce79dbadd0762b4ab7b04ef90cd77dfebe5fb019bd33c5417b0bab2
7
+ data.tar.gz: cd1fbd57591dabb7b8ccbf4862e3c0ee3cbb2c2a9c6f0f9e6e2584066c6fbf4b5b77eaaa40ca0bc3638c2c805244991d56704ce9acb2b4a7aed3f0b682718389
data/config/default.yml CHANGED
@@ -43,6 +43,10 @@ gemfile: false
43
43
  # to the root of the repository.
44
44
  plugin_directory: '.git-hooks'
45
45
 
46
+ # Explicit namespaces for gem-provided hooks. No gems are loaded by default.
47
+ # Example: { Company: overcommit-company }
48
+ gem_plugins: {}
49
+
46
50
  # Whether to hide hook output by default. This results in completely silent hook
47
51
  # runs except in the case of warning or failure.
48
52
  quiet: false
@@ -165,6 +169,7 @@ PreCommit:
165
169
  description: 'Check for vulnerable versions of gems'
166
170
  required_executable: 'bundle-audit'
167
171
  install_command: 'gem install bundler-audit'
172
+ update: false # Update ruby-advisory-db before checking for vulnerabilities
168
173
 
169
174
  BundleCheck:
170
175
  enabled: false
@@ -949,6 +954,57 @@ PreCommit:
949
954
  install_command: 'gem install travis'
950
955
  include: '.travis.yml'
951
956
 
957
+ Vale:
958
+ enabled: false
959
+ description: 'Check spelling and style with Vale'
960
+ required_executable: 'vale'
961
+ install_command: 'brew install vale'
962
+ message_pattern: !ruby/regexp /^(?<file>(?:\w:)?[^:]+):(?<line>[0-9]+):/
963
+ flags: ['--output=line']
964
+ include:
965
+ # Text, markup, and source formats supported by Vale. Some formats require
966
+ # additional software/configuration; use 'exclude' to disable them.
967
+ - '**/*.adoc'
968
+ - '**/*.bsh'
969
+ - '**/*.c'
970
+ - '**/*.cc'
971
+ - '**/*.cpp'
972
+ - '**/*.cs'
973
+ - '**/*.css'
974
+ - '**/*.csx'
975
+ - '**/*.cxx'
976
+ - '**/*.dita'
977
+ - '**/*.java'
978
+ - '**/*.js'
979
+ - '**/*.go'
980
+ - '**/*.h'
981
+ - '**/*.hpp'
982
+ - '**/*.hs'
983
+ - '**/*.html'
984
+ - '**/*.less'
985
+ - '**/*.lua'
986
+ - '**/*.md'
987
+ - '**/*.php'
988
+ - '**/*.pl'
989
+ - '**/*.pm'
990
+ - '**/*.pod'
991
+ - '**/*.py'
992
+ - '**/*.py3'
993
+ - '**/*.pyi'
994
+ - '**/*.pyw'
995
+ - '**/*.R'
996
+ - '**/*.r'
997
+ - '**/*.rb'
998
+ - '**/*.rpy'
999
+ - '**/*.rst'
1000
+ - '**/*.sass'
1001
+ - '**/*.sbt'
1002
+ - '**/*.scala'
1003
+ - '**/*.swift'
1004
+ - '**/*.txt'
1005
+ - '**/*.xhtml'
1006
+ - '**/*.xml'
1007
+
952
1008
  Vint:
953
1009
  enabled: false
954
1010
  description: 'Analyze with Vint'
@@ -17,7 +17,7 @@ module Overcommit
17
17
  Overcommit::Utils.log = logger
18
18
  end
19
19
 
20
- def run
20
+ def run # rubocop:disable Metrics/MethodLength
21
21
  parse_arguments
22
22
 
23
23
  case @options[:action]
@@ -35,6 +35,12 @@ module Overcommit
35
35
  rescue Overcommit::Exceptions::ConfigurationSignatureChanged => e
36
36
  puts e
37
37
  exit 78 # EX_CONFIG
38
+ rescue Overcommit::Exceptions::InvalidHookSignature
39
+ exit 78 # EX_CONFIG
40
+ rescue Overcommit::Exceptions::ConfigurationError,
41
+ Overcommit::Exceptions::HookLoadError => e
42
+ puts e
43
+ exit 78 # EX_CONFIG
38
44
  rescue Overcommit::Exceptions::HookContextLoadError => e
39
45
  puts e
40
46
  exit 64 # EX_USAGE
@@ -127,12 +127,19 @@ module Overcommit
127
127
  select { |hook_name| hook_enabled?(hook_context, hook_name) }
128
128
  end
129
129
 
130
+ # Gem hooks are explicitly namespaced; discovery never executes gem code.
131
+ def enabled_gem_hooks(hook_context)
132
+ @hash[hook_context.hook_class_name].keys.select do |hook_name|
133
+ hook_name.include?('::') && hook_enabled?(hook_context, hook_name)
134
+ end
135
+ end
136
+
130
137
  # Returns a non-modifiable configuration for a hook.
131
138
  def for_hook(hook, hook_type = nil)
132
139
  unless hook_type
133
140
  components = hook.class.name.split('::')
134
- hook = components.last
135
- hook_type = components[-2]
141
+ hook = components[3..].join('::')
142
+ hook_type = components[2]
136
143
  end
137
144
 
138
145
  # Merge hook configuration with special 'ALL' config
@@ -155,8 +162,9 @@ module Overcommit
155
162
  # Applies additional configuration settings based on the provided
156
163
  # environment variables.
157
164
  def apply_environment!(hook_context, env)
158
- skipped_hooks = "#{env['SKIP']} #{env['SKIP_CHECKS']} #{env['SKIP_HOOKS']}".split(/[:, ]/)
159
- only_hooks = env.fetch('ONLY') { '' }.split(/[:, ]/)
165
+ separator = /(?<!:):(?!:)|[, ]/
166
+ skipped_hooks = "#{env['SKIP']} #{env['SKIP_CHECKS']} #{env['SKIP_HOOKS']}".split(separator)
167
+ only_hooks = env.fetch('ONLY') { '' }.split(separator)
160
168
  hook_type = hook_context.hook_class_name
161
169
 
162
170
  if only_hooks.any? || skipped_hooks.include?('all') || skipped_hooks.include?('ALL')
@@ -179,6 +187,10 @@ module Overcommit
179
187
  end
180
188
 
181
189
  def plugin_hook?(hook_context_or_type, hook_name)
190
+ if hook_name.include?('::')
191
+ return (@hash['gem_plugins'] || {}).key?(hook_name.split('::').first)
192
+ end
193
+
182
194
  hook_type_name =
183
195
  if hook_context_or_type.is_a?(String)
184
196
  Overcommit::Utils.snake_case(hook_context_or_type)
@@ -190,12 +202,11 @@ module Overcommit
190
202
  File.exist?(File.join(plugin_directory, hook_type_name, "#{hook_name}.rb"))
191
203
  end
192
204
 
193
- # Return whether the signature for this configuration has changed since it
194
- # was last calculated.
205
+ # Return whether this configuration has been explicitly trusted before.
195
206
  #
196
207
  # @return [true,false]
197
- def signature_changed?
198
- signature != stored_signature
208
+ def signature_verified?
209
+ signature_store.include?(signature)
199
210
  end
200
211
 
201
212
  # Return whether a previous signature has been recorded for this
@@ -203,7 +214,7 @@ module Overcommit
203
214
  #
204
215
  # @return [true,false]
205
216
  def previous_signature?
206
- !stored_signature.empty?
217
+ signature_store.recorded?
207
218
  end
208
219
 
209
220
  # Returns whether this configuration should verify itself by checking the
@@ -233,13 +244,10 @@ module Overcommit
233
244
 
234
245
  # Update the currently stored signature for this hook.
235
246
  def update_signature!
247
+ signature_store.add(signature)
236
248
  scope = Overcommit::GitConfig.signature_scope
237
- result = Overcommit::Utils.execute(
238
- %W[git config #{scope}] + [signature_config_key, signature]
239
- )
240
-
241
249
  verify_signature_value = @hash['verify_signatures'] ? 1 : 0
242
- result &&= Overcommit::Utils.execute(
250
+ result = Overcommit::Utils.execute(
243
251
  %W[git config #{scope} #{verify_signature_config_key} #{verify_signature_value}]
244
252
  )
245
253
 
@@ -261,11 +269,14 @@ module Overcommit
261
269
  # Ad hoc hooks are neither built-in nor have a plugin file written but
262
270
  # still have a `command` specified to be run
263
271
  !built_in_hook?(hook_context, hook_name) &&
272
+ !hook_name.include?('::') &&
264
273
  !plugin_hook?(hook_context, hook_name) &&
265
274
  (ad_hoc_conf['command'] || ad_hoc_conf['required_executable'])
266
275
  end
267
276
 
268
277
  def built_in_hook?(hook_context, hook_name)
278
+ return false if hook_name.include?('::')
279
+
269
280
  hook_name = Overcommit::Utils.snake_case(hook_name)
270
281
 
271
282
  File.exist?(File.join(Overcommit::HOME, 'lib', 'overcommit', 'hook',
@@ -320,26 +331,8 @@ module Overcommit
320
331
  Digest::SHA256.hexdigest(@hash.to_json)
321
332
  end
322
333
 
323
- # Returns the stored signature of this repo's Overcommit configuration.
324
- #
325
- # This is intended to be compared against the current signature of this
326
- # configuration object.
327
- #
328
- # @return [String]
329
- def stored_signature
330
- scope = Overcommit::GitConfig.signature_scope
331
- result = Overcommit::Utils.execute(
332
- %W[git config #{scope} --get] + [signature_config_key]
333
- )
334
-
335
- if result.status == 1 # Key doesn't exist
336
- return ''
337
- elsif result.status != 0
338
- raise Overcommit::Exceptions::GitConfigError,
339
- "Unable to read from local repo git config: #{result.stderr}"
340
- end
341
-
342
- result.stdout.chomp
334
+ def signature_store
335
+ @signature_store ||= Overcommit::Signature.new(signature_config_key)
343
336
  end
344
337
 
345
338
  def signature_config_key
@@ -28,7 +28,7 @@ module Overcommit
28
28
  # default. Explicitly enable aliases if the option is available.
29
29
  yaml =
30
30
  begin
31
- YAML.load_file(file, aliases: true)
31
+ YAML.load_file(file, permitted_classes: [Regexp, Symbol], aliases: true)
32
32
  rescue ArgumentError
33
33
  YAML.load_file(file)
34
34
  end
@@ -95,7 +95,7 @@ module Overcommit
95
95
  "No previously recorded signature for configuration file.\n" \
96
96
  'Run `overcommit --sign` if you trust the hooks in this repository.'
97
97
 
98
- elsif config.signature_changed?
98
+ elsif !config.signature_verified?
99
99
  raise Overcommit::Exceptions::ConfigurationSignatureChanged,
100
100
  "Signature of configuration file has changed!\n" \
101
101
  "Run `overcommit --sign` once you've verified the configuration changes."
@@ -18,6 +18,7 @@ module Overcommit
18
18
 
19
19
  hash = convert_nils_to_empty_hashes(hash)
20
20
  ensure_hook_type_sections_exist(hash)
21
+ check_gem_plugins(hash)
21
22
  check_hook_name_format(hash)
22
23
  check_hook_env(hash)
23
24
  check_for_missing_enabled_option(hash) unless @options[:default]
@@ -29,6 +30,19 @@ module Overcommit
29
30
 
30
31
  private
31
32
 
33
+ # Validate declarations without resolving, activating, or requiring gems.
34
+ def check_gem_plugins(hash)
35
+ plugins = hash.fetch('gem_plugins', {})
36
+ valid = plugins.is_a?(Hash) && plugins.all? do |namespace, gem_name|
37
+ namespace.is_a?(String) && namespace.match?(/\A[A-Z][A-Za-z0-9]*\z/) &&
38
+ gem_name.is_a?(String) && gem_name.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_.-]*\z/)
39
+ end
40
+ return if valid
41
+
42
+ raise Overcommit::Exceptions::ConfigurationError,
43
+ '`gem_plugins` must map CamelCase namespaces to gem names'
44
+ end
45
+
32
46
  # Ensures that keys for all supported hook types exist (PreCommit,
33
47
  # CommitMsg, etc.)
34
48
  def ensure_hook_type_sections_exist(hash)
@@ -102,10 +116,10 @@ module Overcommit
102
116
  hash.fetch(hook_type) { {} }.each_key do |hook_name|
103
117
  next if hook_name == 'ALL'
104
118
 
105
- unless hook_name.match?(/\A[A-Za-z0-9]+\z/)
119
+ unless hook_name.match?(/\A(?:[A-Z][A-Za-z0-9]*::[A-Z][A-Za-z0-9]*|[A-Za-z0-9]+)\z/)
106
120
  errors << "#{hook_type}::#{hook_name} has an invalid name " \
107
- "#{hook_name}. It must contain only alphanumeric " \
108
- 'characters (no underscores or dashes, etc.)'
121
+ "#{hook_name}. Use an alphanumeric name or Namespace::HookName " \
122
+ '(no underscores or dashes, etc.)'
109
123
  end
110
124
  end
111
125
  end
@@ -13,6 +13,9 @@ module Overcommit::Exceptions
13
13
  # Raised when trying to read/write to/from the local repo git config fails.
14
14
  class GitConfigError < Error; end
15
15
 
16
+ # Raised when local signature history cannot be read or written.
17
+ class SignatureError < Error; end
18
+
16
19
  # Raised when there was a problem reading submodule information for a repo.
17
20
  class GitSubmoduleError < Error; end
18
21
 
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+ require 'find'
5
+ require 'json'
6
+
7
+ module Overcommit
8
+ # A gem source and its approval, resolved without requiring its entrypoint.
9
+ class GemPlugin # rubocop:disable Metrics/ClassLength
10
+ attr_reader :namespace, :hook_names
11
+
12
+ def initialize(namespace, config, context)
13
+ @namespace = namespace
14
+ @config = config
15
+ @context = context
16
+ @gem_name = (config['gem_plugins'] || {})[namespace]
17
+ unless @gem_name
18
+ raise Overcommit::Exceptions::HookLoadError,
19
+ "Declare the gem for #{namespace} in `gem_plugins`"
20
+ end
21
+ @hook_names = config.enabled_gem_hooks(context).
22
+ select { |name| name.start_with?("#{namespace}::") }
23
+ end
24
+
25
+ def hook_name
26
+ "#{namespace} (gem #{@gem_name})"
27
+ end
28
+
29
+ def hook_path
30
+ specification.full_gem_path
31
+ end
32
+
33
+ def signature_verified?
34
+ signature_store.include?(signature)
35
+ end
36
+
37
+ def update_signature!
38
+ signature_store.add(signature)
39
+ end
40
+
41
+ # Resolve every hook before requiring any code, so a missing hook fails closed.
42
+ def hook_paths
43
+ hook_names.map do |name|
44
+ relative = File.join('overcommit', 'hooks', @context.hook_type_name,
45
+ "#{Overcommit::Utils.snake_case(name.split('::').last)}.rb")
46
+ paths = specification.require_paths.map do |root|
47
+ File.expand_path(File.join(root, relative), hook_path)
48
+ end
49
+ path = paths.find { |candidate| File.file?(candidate) }
50
+ path = File.realpath(path) if path
51
+ unless path&.start_with?(File.realpath(hook_path) + File::SEPARATOR)
52
+ raise Overcommit::Exceptions::HookLoadError,
53
+ "Gem #{@gem_name} does not provide #{name} at #{relative}"
54
+ end
55
+ path
56
+ end
57
+ end
58
+
59
+ def activate
60
+ specifications.reverse_each(&:activate)
61
+ rescue Gem::LoadError => e
62
+ raise Overcommit::Exceptions::HookLoadError, "Unable to activate #{@gem_name}: #{e.message}"
63
+ end
64
+
65
+ private
66
+
67
+ def specification
68
+ @specification ||= find_specification(@gem_name)
69
+ end
70
+
71
+ def find_specification(name, requirement = Gem::Requirement.default)
72
+ spec = Gem.loaded_specs[name] || Gem::Specification.find_by_name(name, requirement)
73
+ unless requirement.satisfied_by?(spec.version)
74
+ raise Gem::LoadError, "#{name} #{spec.version} does not satisfy #{requirement}"
75
+ end
76
+
77
+ spec
78
+ rescue Gem::LoadError => e
79
+ raise Overcommit::Exceptions::HookLoadError,
80
+ "Unable to resolve gem plugin #{@gem_name}: #{e.message}. " \
81
+ 'Install the gem and its dependencies; include them in your Gemfile when using Bundler.'
82
+ end
83
+
84
+ def specifications
85
+ @specifications ||= collect_specifications(specification, {}).values.sort_by(&:name)
86
+ end
87
+
88
+ def collect_specifications(spec, found)
89
+ if found.key?(spec.name)
90
+ unless found[spec.name].version == spec.version
91
+ raise Overcommit::Exceptions::HookLoadError, "Conflicting versions of #{spec.name}"
92
+ end
93
+
94
+ return found
95
+ end
96
+
97
+ found[spec.name] = spec
98
+ spec.runtime_dependencies.each do |dependency|
99
+ # Overcommit itself is already running and trusted, like built-in hooks.
100
+ next if dependency.name == 'overcommit'
101
+
102
+ collect_specifications(find_specification(dependency.name, dependency.requirement), found)
103
+ end
104
+ found
105
+ end
106
+
107
+ def signature
108
+ digest = Digest::SHA256.new
109
+ settings = hook_names.sort.map do |name|
110
+ hook_config = @config.for_hook(name, @context.hook_class_name).
111
+ reject { |key, _| HookSigner::IGNORED_CONFIG_KEYS.include?(key) }
112
+ [name, hook_config]
113
+ end
114
+ digest << JSON.generate([namespace, @gem_name, settings])
115
+ specifications.each do |spec|
116
+ digest << JSON.generate([spec.full_name, spec.require_paths,
117
+ spec.runtime_dependencies.map(&:to_s).sort])
118
+ gem_roots(spec).each_with_index do |root, index|
119
+ digest << JSON.generate(index)
120
+ sign_directory(digest, root)
121
+ end
122
+ end
123
+ digest.hexdigest
124
+ end
125
+
126
+ def gem_roots(spec)
127
+ roots = [spec.full_gem_path] + spec.full_require_paths
128
+ roots = roots.select { |root| File.directory?(root) }.
129
+ map { |root| File.realpath(root) }.uniq
130
+ if roots.empty?
131
+ raise Overcommit::Exceptions::HookLoadError,
132
+ "Unable to find contents of gem #{spec.full_name} for approval"
133
+ end
134
+
135
+ roots.reject do |root|
136
+ roots.any? { |parent| root.start_with?(parent + File::SEPARATOR) }
137
+ end.sort
138
+ end
139
+
140
+ # Cover helpers, data, added/deleted files, and native extensions, rather
141
+ # than just the selected hook file or a gem's potentially incomplete manifest.
142
+ def sign_directory(digest, root)
143
+ Find.find(root, ignore_error: false) do |path|
144
+ if File.basename(path) == '.git'
145
+ Find.prune
146
+ elsif File.symlink?(path)
147
+ raise Overcommit::Exceptions::HookLoadError,
148
+ "Gem plugin approvals cannot cover symbolic links: #{path}"
149
+ elsif File.file?(path)
150
+ relative = path.delete_prefix(root + File::SEPARATOR)
151
+ digest << JSON.generate([relative, Digest::SHA256.file(path).hexdigest])
152
+ end
153
+ end
154
+ rescue SystemCallError => e
155
+ raise Overcommit::Exceptions::HookLoadError,
156
+ "Unable to read gem plugin #{@gem_name}: #{e.message}"
157
+ end
158
+
159
+ def signature_store
160
+ @signature_store ||= Overcommit::Signature.new(
161
+ "overcommit.#{@context.hook_class_name}.#{namespace}.gemsignature"
162
+ )
163
+ end
164
+ end
165
+ end
@@ -13,6 +13,24 @@ module Overcommit
13
13
  char
14
14
  end
15
15
 
16
+ # Git does not pass cleanup options to commit-msg hooks. Use the invoking
17
+ # command's override, then configuration, and Git's documented editor marker.
18
+ def commit_cleanup_mode
19
+ command = Overcommit::Utils.parent_command.to_s.scrub
20
+ modes = command.scan(
21
+ /(?:\A|\s)["']?--cleanup
22
+ (?:=["']?|["']?\s+["']?)
23
+ (strip|whitespace|verbatim|scissors|default)["']?(?=\s|\z)/x
24
+ )
25
+ mode = modes.last&.first || `git config --get commit.cleanup`.chomp
26
+ Overcommit::Utils.log&.debug("Commit cleanup mode #{mode.inspect} from #{command.inspect}")
27
+ if mode.empty? || mode == 'default'
28
+ ENV['GIT_EDITOR'] == ':' ? 'whitespace' : 'strip'
29
+ else
30
+ mode
31
+ end
32
+ end
33
+
16
34
  def hooks_path
17
35
  path = `git config --get core.hooksPath`.chomp
18
36
  return File.join(Overcommit::Utils.git_dir, 'hooks') if path.empty?
@@ -136,9 +136,20 @@ module Overcommit
136
136
  #
137
137
  # @return [Array<String>] list of absolute file paths
138
138
  def all_files
139
- deleted_files = `git ls-files --deleted`.split(/\n/)
139
+ deleted_files, tracked_files = [%w[git ls-files -z --deleted],
140
+ %w[git ls-files -z]].map do |command|
141
+ result = Overcommit::Utils.execute(command)
142
+ unless result.success?
143
+ raise Overcommit::Exceptions::Error,
144
+ "Error listing files. EXIT STATUS: #{result.status}.\n" \
145
+ "STDOUT: #{result.stdout}.\n" \
146
+ "STDERR: #{result.stderr}."
147
+ end
148
+
149
+ result.stdout.split("\0")
150
+ end
140
151
 
141
- (`git ls-files`.split(/\n/) - deleted_files).
152
+ (tracked_files - deleted_files).
142
153
  map { |relative_file| File.expand_path(relative_file) }.
143
154
  reject { |file| File.directory?(file) } # Exclude submodule directories
144
155
  end
@@ -52,7 +52,7 @@ module Overcommit::Hook
52
52
  end
53
53
 
54
54
  def name
55
- self.class.name.split('::').last
55
+ self.class.name.split('::')[3..].join('::')
56
56
  end
57
57
 
58
58
  def description
@@ -12,7 +12,11 @@ module Overcommit::Hook::CommitMsg
12
12
  MISSPELLING_REGEX = /^[&#]\s(?<word>\w+)(?:.+?:\s(?<suggestions>.*))?/.freeze
13
13
 
14
14
  def run
15
- result = execute(command + [uncommented_commit_msg_file])
15
+ result = ::Tempfile.create('commit-msg') do |file|
16
+ file.write(commit_message)
17
+ file.close
18
+ execute(command + [file.path])
19
+ end
16
20
  return [:fail, "Error running spellcheck: #{result.stderr.chomp}"] unless result.success?
17
21
 
18
22
  misspellings = parse_misspellings(result.stdout)
@@ -29,13 +33,6 @@ module Overcommit::Hook::CommitMsg
29
33
 
30
34
  private
31
35
 
32
- def uncommented_commit_msg_file
33
- ::Tempfile.open('commit-msg') do |file|
34
- file.write(commit_message)
35
- file.path
36
- end
37
- end
38
-
39
36
  def parse_misspellings(output)
40
37
  output.scan(MISSPELLING_REGEX).map do |word, suggestions|
41
38
  Misspelling.new(word, suggestions)
@@ -3,6 +3,8 @@
3
3
  module Overcommit::Hook::PreCommit
4
4
  # Checks for vulnerable versions of gems in Gemfile.lock.
5
5
  #
6
+ # Set `update: true` to refresh ruby-advisory-db before checking. Defaults to false.
7
+ #
6
8
  # @see https://github.com/rubysec/bundler-audit
7
9
  class BundleAudit < Base
8
10
  LOCK_FILE = 'Gemfile.lock'
@@ -13,7 +15,10 @@ module Overcommit::Hook::PreCommit
13
15
  stdout.split("\n")
14
16
  return :pass if ignored_files.include?(LOCK_FILE)
15
17
 
16
- result = execute(command)
18
+ audit_command = command
19
+ audit_command << '--update' if config['update']
20
+
21
+ result = execute(audit_command)
17
22
  if result.success?
18
23
  :pass
19
24
  else
@@ -9,8 +9,7 @@ module Overcommit::Hook::PreCommit
9
9
  messages = []
10
10
 
11
11
  offending_files.map do |file_name|
12
- file = File.open(file_name)
13
- begin
12
+ File.open(file_name) do |file|
14
13
  messages += check_file(file, file_name)
15
14
  rescue ArgumentError => e
16
15
  # File is likely a binary file which this check should ignore, but
@@ -7,7 +7,7 @@ module Overcommit::Hook::PreCommit
7
7
  messages = []
8
8
 
9
9
  applicable_files.each do |file|
10
- YAML.load_file(file, aliases: true)
10
+ YAML.load_file(file, permitted_classes: [Regexp, Symbol], aliases: true)
11
11
  rescue ArgumentError
12
12
  begin
13
13
  YAML.load_file(file)