overcommit 0.23.0 → 0.24.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/overcommit +1 -1
- data/config/default.yml +154 -18
- data/config/starter.yml +3 -3
- data/lib/overcommit.rb +2 -1
- data/lib/overcommit/cli.rb +11 -8
- data/lib/overcommit/configuration.rb +18 -4
- data/lib/overcommit/configuration_loader.rb +45 -28
- data/lib/overcommit/configuration_validator.rb +33 -1
- data/lib/overcommit/constants.rb +5 -3
- data/lib/overcommit/exceptions.rb +3 -0
- data/lib/overcommit/git_repo.rb +116 -0
- data/lib/overcommit/git_version.rb +15 -0
- data/lib/overcommit/hook/base.rb +42 -5
- data/lib/overcommit/hook/commit_msg/capitalized_subject.rb +13 -0
- data/lib/overcommit/hook/commit_msg/spell_check.rb +41 -0
- data/lib/overcommit/hook/post_checkout/submodule_status.rb +30 -0
- data/lib/overcommit/hook/post_commit/submodule_status.rb +30 -0
- data/lib/overcommit/hook/post_merge/submodule_status.rb +30 -0
- data/lib/overcommit/hook/post_rewrite/submodule_status.rb +30 -0
- data/lib/overcommit/hook/pre_commit/base.rb +2 -2
- data/lib/overcommit/hook/pre_commit/bundle_check.rb +1 -1
- data/lib/overcommit/hook/pre_commit/case_conflicts.rb +20 -0
- data/lib/overcommit/hook/pre_commit/coffee_lint.rb +29 -2
- data/lib/overcommit/hook/pre_commit/css_lint.rb +1 -8
- data/lib/overcommit/hook/pre_commit/go_lint.rb +8 -2
- data/lib/overcommit/hook/pre_commit/go_vet.rb +20 -0
- data/lib/overcommit/hook/pre_commit/html_tidy.rb +1 -10
- data/lib/overcommit/hook/pre_commit/image_optim.rb +11 -28
- data/lib/overcommit/hook/pre_commit/js_lint.rb +18 -0
- data/lib/overcommit/hook/pre_commit/jsl.rb +24 -0
- data/lib/overcommit/hook/pre_commit/json_syntax.rb +4 -7
- data/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +1 -1
- data/lib/overcommit/hook/pre_commit/ruby_lint.rb +19 -0
- data/lib/overcommit/hook/pre_commit/scss_lint.rb +8 -1
- data/lib/overcommit/hook/pre_commit/w3c_css.rb +4 -18
- data/lib/overcommit/hook/pre_commit/w3c_html.rb +4 -18
- data/lib/overcommit/hook/pre_commit/xml_syntax.rb +19 -0
- data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +4 -8
- data/lib/overcommit/hook/pre_push/base.rb +10 -0
- data/lib/overcommit/hook/pre_push/protected_branches.rb +27 -0
- data/lib/overcommit/hook/pre_push/r_spec.rb +12 -0
- data/lib/overcommit/hook/pre_rebase/base.rb +11 -0
- data/lib/overcommit/hook_context.rb +2 -2
- data/lib/overcommit/hook_context/base.rb +5 -7
- data/lib/overcommit/hook_context/pre_commit.rb +66 -16
- data/lib/overcommit/hook_context/pre_push.rb +44 -0
- data/lib/overcommit/hook_context/pre_rebase.rb +36 -0
- data/lib/overcommit/hook_runner.rb +27 -7
- data/lib/overcommit/installer.rb +46 -7
- data/lib/overcommit/message_processor.rb +3 -0
- data/lib/overcommit/printer.rb +8 -12
- data/lib/overcommit/subprocess.rb +11 -0
- data/lib/overcommit/utils.rb +28 -6
- data/lib/overcommit/version.rb +1 -1
- data/template-dir/hooks/commit-msg +2 -2
- data/template-dir/hooks/overcommit-hook +2 -2
- data/template-dir/hooks/post-checkout +2 -2
- data/template-dir/hooks/post-commit +2 -2
- data/template-dir/hooks/post-merge +2 -2
- data/template-dir/hooks/post-rewrite +2 -2
- data/template-dir/hooks/pre-commit +2 -2
- data/template-dir/hooks/pre-push +81 -0
- data/template-dir/hooks/pre-rebase +81 -0
- metadata +33 -13
- data/lib/overcommit/hook/pre_commit/pry_binding.rb +0 -14
@@ -0,0 +1,15 @@
|
|
1
|
+
# Returns the version of the available git binary.
|
2
|
+
#
|
3
|
+
# This is intended to be used to conveniently execute code based on a specific
|
4
|
+
# git version. Simply compare to a version string:
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# if GIT_VERSION <= '1.8.5'
|
8
|
+
# ...
|
9
|
+
# end
|
10
|
+
module Overcommit
|
11
|
+
GIT_VERSION = begin
|
12
|
+
version = `git --version`.chomp[/[\d\.]+/, 0]
|
13
|
+
Overcommit::Utils::Version.new(version)
|
14
|
+
end
|
15
|
+
end
|
data/lib/overcommit/hook/base.rb
CHANGED
@@ -39,7 +39,7 @@ module Overcommit::Hook
|
|
39
39
|
# implement `#run`, and we needed a wrapper step to transform the status
|
40
40
|
# based on any custom configuration.
|
41
41
|
def run_and_transform
|
42
|
-
if output =
|
42
|
+
if output = check_for_requirements
|
43
43
|
status = :fail
|
44
44
|
else
|
45
45
|
status, output = process_hook_return_value(run)
|
@@ -62,7 +62,7 @@ module Overcommit::Hook
|
|
62
62
|
# @return [Array<Symbol,String>] tuple of status and output
|
63
63
|
def process_hook_return_value(hook_return_value)
|
64
64
|
if hook_return_value.is_a?(Array) &&
|
65
|
-
hook_return_value.first.is_a?(Message)
|
65
|
+
(hook_return_value.first.is_a?(Message) || hook_return_value.empty?)
|
66
66
|
# Process messages into a status and output
|
67
67
|
Overcommit::MessageProcessor.new(
|
68
68
|
self,
|
@@ -119,6 +119,10 @@ module Overcommit::Hook
|
|
119
119
|
@config['required_executable']
|
120
120
|
end
|
121
121
|
|
122
|
+
def required_libraries
|
123
|
+
Array(@config['required_library'] || @config['required_libraries'])
|
124
|
+
end
|
125
|
+
|
122
126
|
# Return command to execute for this hook.
|
123
127
|
#
|
124
128
|
# This is intended to be configurable so hooks can prefix their commands
|
@@ -179,18 +183,51 @@ module Overcommit::Hook
|
|
179
183
|
included && !excluded
|
180
184
|
end
|
181
185
|
|
186
|
+
# Check for any required executables or libraries.
|
187
|
+
#
|
188
|
+
# Returns output if any requirements are not met.
|
189
|
+
def check_for_requirements
|
190
|
+
check_for_executable || check_for_libraries
|
191
|
+
end
|
192
|
+
|
182
193
|
# If the hook defines a required executable, check if it's in the path and
|
183
194
|
# display the install command if one exists.
|
184
195
|
def check_for_executable
|
185
196
|
return unless required_executable && !in_path?(required_executable)
|
186
197
|
|
187
198
|
output = "'#{required_executable}' is not installed (or is not in your PATH)"
|
199
|
+
output << install_command_prompt
|
200
|
+
|
201
|
+
output
|
202
|
+
end
|
188
203
|
|
204
|
+
def install_command_prompt
|
189
205
|
if install_command = @config['install_command']
|
190
|
-
|
206
|
+
"\nInstall it by running: #{install_command}"
|
207
|
+
else
|
208
|
+
''
|
191
209
|
end
|
210
|
+
end
|
192
211
|
|
193
|
-
|
212
|
+
# If the hook defines required library paths that it wants to load, attempt
|
213
|
+
# to load them.
|
214
|
+
def check_for_libraries
|
215
|
+
output = []
|
216
|
+
|
217
|
+
required_libraries.each do |library|
|
218
|
+
begin
|
219
|
+
require library
|
220
|
+
rescue LoadError
|
221
|
+
install_command = @config['install_command']
|
222
|
+
install_command = " -- install via #{install_command}" if install_command
|
223
|
+
|
224
|
+
output << "Unable to load '#{library}'#{install_command}"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
return if output.empty?
|
229
|
+
|
230
|
+
output.join("\n")
|
194
231
|
end
|
195
232
|
|
196
233
|
# Transforms the hook's status based on custom configuration.
|
@@ -198,7 +235,7 @@ module Overcommit::Hook
|
|
198
235
|
# This allows users to change failures into warnings, or vice versa.
|
199
236
|
def transform_status(status)
|
200
237
|
case status
|
201
|
-
when :fail
|
238
|
+
when :fail
|
202
239
|
@config.fetch('on_fail', :fail).to_sym
|
203
240
|
when :warn
|
204
241
|
@config.fetch('on_warn', :warn).to_sym
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Overcommit::Hook::CommitMsg
|
2
|
+
# Ensures commit message subject lines start with a capital letter.
|
3
|
+
class CapitalizedSubject < Base
|
4
|
+
def run
|
5
|
+
first_letter = commit_message_lines[0].to_s.match(/^[[:punct:]]*(.)/)[1]
|
6
|
+
unless first_letter.match(/[[:upper:]]/)
|
7
|
+
return :warn, 'Subject should start with a capital letter'
|
8
|
+
end
|
9
|
+
|
10
|
+
:pass
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Overcommit::Hook::CommitMsg
|
4
|
+
# Checks the commit message for potential misspellings
|
5
|
+
class SpellCheck < Base
|
6
|
+
Misspelling = Struct.new(:word, :suggestions)
|
7
|
+
|
8
|
+
MISSPELLING_REGEX = /^[&#]\s(?<word>\w+)(?:.+?:\s(?<suggestions>.*))?/
|
9
|
+
|
10
|
+
def run
|
11
|
+
result = execute(command + [uncommented_commit_msg_file])
|
12
|
+
return [:fail, "Error running spellcheck: #{result.stderr.chomp}"] unless result.success?
|
13
|
+
|
14
|
+
misspellings = parse_misspellings(result.stdout)
|
15
|
+
return :pass if misspellings.empty?
|
16
|
+
|
17
|
+
messages = misspellings.map do |misspelled|
|
18
|
+
msg = "Potential misspelling: #{misspelled.word}."
|
19
|
+
msg += " Suggestions: #{misspelled.suggestions}" unless misspelled.suggestions.nil?
|
20
|
+
msg
|
21
|
+
end
|
22
|
+
|
23
|
+
[:warn, messages.join("\n")]
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def uncommented_commit_msg_file
|
29
|
+
::Tempfile.open('commit-msg') do |file|
|
30
|
+
file.write(commit_message)
|
31
|
+
file.path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_misspellings(output)
|
36
|
+
output.scan(MISSPELLING_REGEX).map do |word, suggestions|
|
37
|
+
Misspelling.new(word, suggestions)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Overcommit::Hook::PostCheckout
|
2
|
+
# Checks the status of submodules in the current repository and
|
3
|
+
# notifies the user if any are uninitialized, out of date with
|
4
|
+
# the current index, or contain merge conflicts.
|
5
|
+
class SubmoduleStatus < Base
|
6
|
+
def run
|
7
|
+
messages = []
|
8
|
+
submodule_statuses.each do |submodule_status|
|
9
|
+
path = submodule_status.path
|
10
|
+
if submodule_status.uninitialized?
|
11
|
+
messages << "Submodule #{path} is uninitialized."
|
12
|
+
elsif submodule_status.outdated?
|
13
|
+
messages << "Submodule #{path} is out of date with the current index."
|
14
|
+
elsif submodule_status.merge_conflict?
|
15
|
+
messages << "Submodule #{path} has merge conflicts."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
return :pass if messages.empty?
|
20
|
+
|
21
|
+
[:warn, messages.join("\n")]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def submodule_statuses
|
27
|
+
Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Overcommit::Hook::PostCommit
|
2
|
+
# Checks the status of submodules in the current repository and
|
3
|
+
# notifies the user if any are uninitialized, out of date with
|
4
|
+
# the current index, or contain merge conflicts.
|
5
|
+
class SubmoduleStatus < Base
|
6
|
+
def run
|
7
|
+
messages = []
|
8
|
+
submodule_statuses.each do |submodule_status|
|
9
|
+
path = submodule_status.path
|
10
|
+
if submodule_status.uninitialized?
|
11
|
+
messages << "Submodule #{path} is uninitialized."
|
12
|
+
elsif submodule_status.outdated?
|
13
|
+
messages << "Submodule #{path} is out of date with the current index."
|
14
|
+
elsif submodule_status.merge_conflict?
|
15
|
+
messages << "Submodule #{path} has merge conflicts."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
return :pass if messages.empty?
|
20
|
+
|
21
|
+
[:warn, messages.join("\n")]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def submodule_statuses
|
27
|
+
Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Overcommit::Hook::PostMerge
|
2
|
+
# Checks the status of submodules in the current repository and
|
3
|
+
# notifies the user if any are uninitialized, out of date with
|
4
|
+
# the current index, or contain merge conflicts.
|
5
|
+
class SubmoduleStatus < Base
|
6
|
+
def run
|
7
|
+
messages = []
|
8
|
+
submodule_statuses.each do |submodule_status|
|
9
|
+
path = submodule_status.path
|
10
|
+
if submodule_status.uninitialized?
|
11
|
+
messages << "Submodule #{path} is uninitialized."
|
12
|
+
elsif submodule_status.outdated?
|
13
|
+
messages << "Submodule #{path} is out of date with the current index."
|
14
|
+
elsif submodule_status.merge_conflict?
|
15
|
+
messages << "Submodule #{path} has merge conflicts."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
return :pass if messages.empty?
|
20
|
+
|
21
|
+
[:warn, messages.join("\n")]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def submodule_statuses
|
27
|
+
Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Overcommit::Hook::PostRewrite
|
2
|
+
# Checks the status of submodules in the current repository and
|
3
|
+
# notifies the user if any are uninitialized, out of date with
|
4
|
+
# the current index, or contain merge conflicts.
|
5
|
+
class SubmoduleStatus < Base
|
6
|
+
def run
|
7
|
+
messages = []
|
8
|
+
submodule_statuses.each do |submodule_status|
|
9
|
+
path = submodule_status.path
|
10
|
+
if submodule_status.uninitialized?
|
11
|
+
messages << "Submodule #{path} is uninitialized."
|
12
|
+
elsif submodule_status.outdated?
|
13
|
+
messages << "Submodule #{path} is out of date with the current index."
|
14
|
+
elsif submodule_status.merge_conflict?
|
15
|
+
messages << "Submodule #{path} has merge conflicts."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
return :pass if messages.empty?
|
20
|
+
|
21
|
+
[:warn, messages.join("\n")]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def submodule_statuses
|
27
|
+
Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -5,7 +5,7 @@ module Overcommit::Hook::PreCommit
|
|
5
5
|
class Base < Overcommit::Hook::Base
|
6
6
|
extend Forwardable
|
7
7
|
|
8
|
-
def_delegators :@context, :modified_lines_in_file
|
8
|
+
def_delegators :@context, :modified_lines_in_file, :amendment?
|
9
9
|
|
10
10
|
private
|
11
11
|
|
@@ -32,7 +32,7 @@ module Overcommit::Hook::PreCommit
|
|
32
32
|
end
|
33
33
|
|
34
34
|
file = extract_file(match, message)
|
35
|
-
line = extract_line(match, message)
|
35
|
+
line = extract_line(match, message) unless match[:line].nil?
|
36
36
|
type = extract_type(match, message, type_categorizer)
|
37
37
|
|
38
38
|
Overcommit::Hook::Message.new(type, file, line, message)
|
@@ -16,7 +16,7 @@ module Overcommit::Hook::PreCommit
|
|
16
16
|
|
17
17
|
result = execute(%w[git diff --quiet --] + [LOCK_FILE])
|
18
18
|
unless result.success?
|
19
|
-
return :fail, "#{LOCK_FILE} is not up-to-date -- run `#{command.join(' ')}
|
19
|
+
return :fail, "#{LOCK_FILE} is not up-to-date -- run `#{command.join(' ')}`"
|
20
20
|
end
|
21
21
|
|
22
22
|
:pass
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Checks for files that would conflict in case-insensitive filesystems
|
3
|
+
# Adapted from https://github.com/pre-commit/pre-commit-hooks
|
4
|
+
class CaseConflicts < Base
|
5
|
+
def run
|
6
|
+
paths = Set.new(applicable_files.map { |file| File.dirname(file) + File::SEPARATOR })
|
7
|
+
repo_files = Set.new(Overcommit::GitRepo.list_files(paths.to_a) + applicable_files)
|
8
|
+
conflict_hash = repo_files.classify(&:downcase).
|
9
|
+
select { |_, files| files.size > 1 }
|
10
|
+
conflict_files = applicable_files.
|
11
|
+
select { |file| conflict_hash.include?(file.downcase) }
|
12
|
+
|
13
|
+
conflict_files.map do |file|
|
14
|
+
conflicts = conflict_hash[file.downcase].map { |f| File.basename(f) }
|
15
|
+
msg = "Conflict detected for case-insensitive file systems: #{conflicts.join(', ')}"
|
16
|
+
Overcommit::Hook::Message.new(:error, file, nil, msg)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -3,9 +3,36 @@ module Overcommit::Hook::PreCommit
|
|
3
3
|
class CoffeeLint < Base
|
4
4
|
def run
|
5
5
|
result = execute(command + applicable_files)
|
6
|
-
return :pass if result.success?
|
7
6
|
|
8
|
-
|
7
|
+
begin
|
8
|
+
parse_json_messages(result.stdout)
|
9
|
+
rescue JSON::ParserError => e
|
10
|
+
[:fail, "Error parsing coffeelint output: #{e.message}"]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def parse_json_messages(output)
|
17
|
+
JSON.parse(output).collect do |file, messages|
|
18
|
+
messages.collect { |msg| extract_message(file, msg) }
|
19
|
+
end.flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract_message(file, message_hash)
|
23
|
+
type = message_hash['level'].include?('w') ? :warning : :error
|
24
|
+
line = message_hash['lineNumber']
|
25
|
+
rule = message_hash['rule']
|
26
|
+
msg = message_hash['message']
|
27
|
+
text =
|
28
|
+
if rule == 'coffeescript_error'
|
29
|
+
# Syntax errors are output in different format.
|
30
|
+
# Splice in the file name and grab the first line.
|
31
|
+
msg.sub('[stdin]', file).split("\n")[0]
|
32
|
+
else
|
33
|
+
"#{file}:#{line}: #{msg} (#{rule})"
|
34
|
+
end
|
35
|
+
Overcommit::Hook::Message.new(type, file, line, text)
|
9
36
|
end
|
10
37
|
end
|
11
38
|
end
|
@@ -13,17 +13,10 @@ module Overcommit::Hook::PreCommit
|
|
13
13
|
return :pass if result.success? && output.empty?
|
14
14
|
|
15
15
|
extract_messages(
|
16
|
-
output.split("\n").
|
16
|
+
output.split("\n").reject(&:empty?),
|
17
17
|
MESSAGE_REGEX,
|
18
18
|
lambda { |type| type.downcase.to_sym }
|
19
19
|
)
|
20
20
|
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
# Hack to include messages that apply to the entire file
|
25
|
-
def add_line_number(message)
|
26
|
-
message.sub(/(?<!\d,\s)(Error|Warning)/, 'line 0, \1')
|
27
|
-
end
|
28
21
|
end
|
29
22
|
end
|
@@ -3,10 +3,16 @@ module Overcommit::Hook::PreCommit
|
|
3
3
|
class GoLint < Base
|
4
4
|
def run
|
5
5
|
result = execute(command + applicable_files)
|
6
|
+
output = result.stdout + result.stderr
|
6
7
|
# Unfortunately the exit code is always 0
|
7
|
-
return :pass if
|
8
|
+
return :pass if output.empty?
|
8
9
|
|
9
|
-
|
10
|
+
# example message:
|
11
|
+
# path/to/file.go:1:1: Error message
|
12
|
+
extract_messages(
|
13
|
+
output.split("\n"),
|
14
|
+
/^(?<file>[^:]+):(?<line>\d+)/
|
15
|
+
)
|
10
16
|
end
|
11
17
|
end
|
12
18
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `go vet` against any modified Golang files.
|
3
|
+
class GoVet < Base
|
4
|
+
def run
|
5
|
+
result = execute(command + applicable_files)
|
6
|
+
return :pass if result.success?
|
7
|
+
|
8
|
+
if result.stderr =~ /no such tool "vet"/
|
9
|
+
return :fail, "`go tool vet` is not installed#{install_command_prompt}"
|
10
|
+
end
|
11
|
+
|
12
|
+
# example message:
|
13
|
+
# path/to/file.go:7: Error message
|
14
|
+
extract_messages(
|
15
|
+
result.stderr.split("\n"),
|
16
|
+
/^(?<file>[^:]+):(?<line>\d+)/
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -11,19 +11,10 @@ module Overcommit::Hook::PreCommit
|
|
11
11
|
def run
|
12
12
|
# example message:
|
13
13
|
# line 4 column 24 - Warning: <html> proprietary attribute "class"
|
14
|
-
messages = collect_messages
|
15
|
-
|
16
|
-
return :pass if messages.empty?
|
17
|
-
|
18
|
-
messages
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def collect_messages
|
24
14
|
applicable_files.collect do |file|
|
25
15
|
result = execute(command + [file])
|
26
16
|
output = result.stderr.chomp
|
17
|
+
|
27
18
|
extract_messages(
|
28
19
|
output.split("\n").collect { |msg| "#{file}: #{msg}" },
|
29
20
|
MESSAGE_REGEX,
|