jawshooah-overcommit 0.22.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 +7 -0
- data/bin/overcommit +8 -0
- data/config/default.yml +275 -0
- data/config/starter.yml +31 -0
- data/lib/overcommit.rb +20 -0
- data/lib/overcommit/cli.rb +205 -0
- data/lib/overcommit/configuration.rb +183 -0
- data/lib/overcommit/configuration_loader.rb +49 -0
- data/lib/overcommit/configuration_validator.rb +40 -0
- data/lib/overcommit/constants.rb +8 -0
- data/lib/overcommit/exceptions.rb +35 -0
- data/lib/overcommit/git_repo.rb +147 -0
- data/lib/overcommit/hook/base.rb +174 -0
- data/lib/overcommit/hook/commit_msg/base.rb +11 -0
- data/lib/overcommit/hook/commit_msg/gerrit_change_id.rb +18 -0
- data/lib/overcommit/hook/commit_msg/hard_tabs.rb +13 -0
- data/lib/overcommit/hook/commit_msg/russian_novel.rb +14 -0
- data/lib/overcommit/hook/commit_msg/single_line_subject.rb +12 -0
- data/lib/overcommit/hook/commit_msg/text_width.rb +38 -0
- data/lib/overcommit/hook/commit_msg/trailing_period.rb +12 -0
- data/lib/overcommit/hook/post_checkout/base.rb +11 -0
- data/lib/overcommit/hook/post_checkout/index_tags.rb +26 -0
- data/lib/overcommit/hook/post_commit/base.rb +11 -0
- data/lib/overcommit/hook/post_commit/git_guilt.rb +9 -0
- data/lib/overcommit/hook/pre_commit/author_email.rb +18 -0
- data/lib/overcommit/hook/pre_commit/author_name.rb +17 -0
- data/lib/overcommit/hook/pre_commit/base.rb +70 -0
- data/lib/overcommit/hook/pre_commit/berksfile_check.rb +20 -0
- data/lib/overcommit/hook/pre_commit/brakeman.rb +12 -0
- data/lib/overcommit/hook/pre_commit/broken_symlinks.rb +15 -0
- data/lib/overcommit/hook/pre_commit/bundle_check.rb +25 -0
- data/lib/overcommit/hook/pre_commit/chamber_security.rb +11 -0
- data/lib/overcommit/hook/pre_commit/coffee_lint.rb +11 -0
- data/lib/overcommit/hook/pre_commit/css_lint.rb +11 -0
- data/lib/overcommit/hook/pre_commit/go_lint.rb +12 -0
- data/lib/overcommit/hook/pre_commit/haml_lint.rb +19 -0
- data/lib/overcommit/hook/pre_commit/hard_tabs.rb +14 -0
- data/lib/overcommit/hook/pre_commit/image_optim.rb +41 -0
- data/lib/overcommit/hook/pre_commit/js_hint.rb +13 -0
- data/lib/overcommit/hook/pre_commit/jscs.rb +22 -0
- data/lib/overcommit/hook/pre_commit/json_syntax.rb +22 -0
- data/lib/overcommit/hook/pre_commit/jsx_hint.rb +13 -0
- data/lib/overcommit/hook/pre_commit/jsxcs.rb +20 -0
- data/lib/overcommit/hook/pre_commit/local_paths_in_gemfile.rb +14 -0
- data/lib/overcommit/hook/pre_commit/merge_conflicts.rb +14 -0
- data/lib/overcommit/hook/pre_commit/pry_binding.rb +14 -0
- data/lib/overcommit/hook/pre_commit/python_flake8.rb +11 -0
- data/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +45 -0
- data/lib/overcommit/hook/pre_commit/reek.rb +22 -0
- data/lib/overcommit/hook/pre_commit/rubocop.rb +19 -0
- data/lib/overcommit/hook/pre_commit/scss_lint.rb +19 -0
- data/lib/overcommit/hook/pre_commit/shell_check.rb +19 -0
- data/lib/overcommit/hook/pre_commit/trailing_whitespace.rb +13 -0
- data/lib/overcommit/hook/pre_commit/travis_lint.rb +11 -0
- data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +22 -0
- data/lib/overcommit/hook_context.rb +17 -0
- data/lib/overcommit/hook_context/base.rb +69 -0
- data/lib/overcommit/hook_context/commit_msg.rb +32 -0
- data/lib/overcommit/hook_context/post_checkout.rb +26 -0
- data/lib/overcommit/hook_context/post_commit.rb +19 -0
- data/lib/overcommit/hook_context/pre_commit.rb +148 -0
- data/lib/overcommit/hook_context/run_all.rb +39 -0
- data/lib/overcommit/hook_loader/base.rb +36 -0
- data/lib/overcommit/hook_loader/built_in_hook_loader.rb +12 -0
- data/lib/overcommit/hook_loader/plugin_hook_loader.rb +61 -0
- data/lib/overcommit/hook_runner.rb +129 -0
- data/lib/overcommit/hook_signer.rb +79 -0
- data/lib/overcommit/installer.rb +148 -0
- data/lib/overcommit/interrupt_handler.rb +87 -0
- data/lib/overcommit/logger.rb +79 -0
- data/lib/overcommit/message_processor.rb +132 -0
- data/lib/overcommit/printer.rb +116 -0
- data/lib/overcommit/subprocess.rb +46 -0
- data/lib/overcommit/utils.rb +163 -0
- data/lib/overcommit/version.rb +4 -0
- data/libexec/gerrit-change-id +174 -0
- data/libexec/index-tags +17 -0
- data/template-dir/hooks/commit-msg +81 -0
- data/template-dir/hooks/overcommit-hook +81 -0
- data/template-dir/hooks/post-checkout +81 -0
- data/template-dir/hooks/pre-commit +81 -0
- metadata +184 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'overcommit/message_processor'
|
3
|
+
|
4
|
+
# Container for top-level hook-related classes and constants.
|
5
|
+
module Overcommit::Hook
|
6
|
+
# Helper containing metadata about error/warning messages returned by hooks.
|
7
|
+
Message = Struct.new(:type, :file, :line, :content) do
|
8
|
+
def to_s
|
9
|
+
content
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Possible types of messages.
|
14
|
+
MESSAGE_TYPES = [:error, :warning]
|
15
|
+
|
16
|
+
# Functionality common to all hooks.
|
17
|
+
class Base
|
18
|
+
extend Forwardable
|
19
|
+
|
20
|
+
def_delegators :@context, :modified_files
|
21
|
+
attr_reader :config
|
22
|
+
|
23
|
+
# @param config [Overcommit::Configuration]
|
24
|
+
# @param context [Overcommit::HookContext]
|
25
|
+
def initialize(config, context)
|
26
|
+
@config = config.for_hook(self)
|
27
|
+
@context = context
|
28
|
+
end
|
29
|
+
|
30
|
+
# Runs the hook.
|
31
|
+
def run
|
32
|
+
raise NotImplementedError, 'Hook must define `run`'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Runs the hook and transforms the status returned based on the hook's
|
36
|
+
# configuration.
|
37
|
+
#
|
38
|
+
# Poorly named because we already have a bunch of hooks in the wild that
|
39
|
+
# implement `#run`, and we needed a wrapper step to transform the status
|
40
|
+
# based on any custom configuration.
|
41
|
+
def run_and_transform
|
42
|
+
if output = check_for_executable
|
43
|
+
status = :fail
|
44
|
+
else
|
45
|
+
status, output = process_hook_return_value(run)
|
46
|
+
end
|
47
|
+
|
48
|
+
[transform_status(status), output]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts the hook's return value into a canonical form of a tuple
|
52
|
+
# containing status (pass/warn/fail) and output.
|
53
|
+
#
|
54
|
+
# This is intended to support various shortcuts for writing hooks so that
|
55
|
+
# hook authors don't need to work with {Overcommit::Hook::Message} objects
|
56
|
+
# for simple pass/fail hooks. It also saves you from needing to manually
|
57
|
+
# encode logic like "if there are errors, fail; if there are warnings, warn,
|
58
|
+
# otherwise pass." by simply returning an array of
|
59
|
+
# {Overcommit::Hook::Message} objects.
|
60
|
+
#
|
61
|
+
# @param hook_return_value [Symbol, Array<Symbol,String>, Array<Message>]
|
62
|
+
# @return [Array<Symbol,String>] tuple of status and output
|
63
|
+
def process_hook_return_value(hook_return_value)
|
64
|
+
if hook_return_value.is_a?(Array) &&
|
65
|
+
hook_return_value.first.is_a?(Message)
|
66
|
+
# Process messages into a status and output
|
67
|
+
Overcommit::MessageProcessor.new(
|
68
|
+
self,
|
69
|
+
@config['problem_on_unmodified_line'],
|
70
|
+
).hook_result(hook_return_value)
|
71
|
+
else
|
72
|
+
# Otherwise return as-is
|
73
|
+
hook_return_value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def name
|
78
|
+
self.class.name.split('::').last
|
79
|
+
end
|
80
|
+
|
81
|
+
def description
|
82
|
+
@config['description'] || "Running #{name}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def required?
|
86
|
+
@config['required']
|
87
|
+
end
|
88
|
+
|
89
|
+
def quiet?
|
90
|
+
@config['quiet']
|
91
|
+
end
|
92
|
+
|
93
|
+
def enabled?
|
94
|
+
@config['enabled'] != false
|
95
|
+
end
|
96
|
+
|
97
|
+
def skip?
|
98
|
+
@config['skip']
|
99
|
+
end
|
100
|
+
|
101
|
+
def run?
|
102
|
+
enabled? &&
|
103
|
+
!(@config['requires_files'] && applicable_files.empty?)
|
104
|
+
end
|
105
|
+
|
106
|
+
def in_path?(cmd)
|
107
|
+
Overcommit::Utils.in_path?(cmd)
|
108
|
+
end
|
109
|
+
|
110
|
+
def execute(cmd)
|
111
|
+
Overcommit::Utils.execute(cmd)
|
112
|
+
end
|
113
|
+
|
114
|
+
def executable
|
115
|
+
@config['required_executable']
|
116
|
+
end
|
117
|
+
|
118
|
+
# Gets a list of staged files that apply to this hook based on its
|
119
|
+
# configured `include` and `exclude` lists.
|
120
|
+
def applicable_files
|
121
|
+
@applicable_files ||= modified_files.select { |file| applicable_file?(file) }
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def applicable_file?(file)
|
127
|
+
includes = Array(@config['include']).map do |glob|
|
128
|
+
Overcommit::Utils.convert_glob_to_absolute(glob)
|
129
|
+
end
|
130
|
+
|
131
|
+
included = includes.empty? || includes.any? do |glob|
|
132
|
+
Overcommit::Utils.matches_path?(glob, file)
|
133
|
+
end
|
134
|
+
|
135
|
+
excludes = Array(@config['exclude']).map do |glob|
|
136
|
+
Overcommit::Utils.convert_glob_to_absolute(glob)
|
137
|
+
end
|
138
|
+
|
139
|
+
excluded = excludes.any? do |glob|
|
140
|
+
Overcommit::Utils.matches_path?(glob, file)
|
141
|
+
end
|
142
|
+
|
143
|
+
included && !excluded
|
144
|
+
end
|
145
|
+
|
146
|
+
# If the hook defines a required executable, check if it's in the path and
|
147
|
+
# display the install command if one exists.
|
148
|
+
def check_for_executable
|
149
|
+
return unless executable && !in_path?(executable)
|
150
|
+
|
151
|
+
output = "'#{executable}' is not installed (or is not in your PATH)"
|
152
|
+
|
153
|
+
if install_command = @config['install_command']
|
154
|
+
output += "\nInstall it by running: #{install_command}"
|
155
|
+
end
|
156
|
+
|
157
|
+
output
|
158
|
+
end
|
159
|
+
|
160
|
+
# Transforms the hook's status based on custom configuration.
|
161
|
+
#
|
162
|
+
# This allows users to change failures into warnings, or vice versa.
|
163
|
+
def transform_status(status)
|
164
|
+
case status
|
165
|
+
when :fail, :bad
|
166
|
+
@config.fetch('on_fail', :fail).to_sym
|
167
|
+
when :warn
|
168
|
+
@config.fetch('on_warn', :warn).to_sym
|
169
|
+
else
|
170
|
+
status
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Overcommit::Hook::CommitMsg
|
4
|
+
# Functionality common to all commit-msg hooks.
|
5
|
+
class Base < Overcommit::Hook::Base
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@context, :commit_message, :update_commit_message,
|
9
|
+
:commit_message_lines, :commit_message_file
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Overcommit::Hook::CommitMsg
|
2
|
+
# Ensures a Gerrit Change-Id line is included in the commit message.
|
3
|
+
#
|
4
|
+
# It may seem odd to do this here instead of in a prepare-commit-msg hook, but
|
5
|
+
# the reality is that if you want to _ensure_ the Change-Id is included then
|
6
|
+
# you need to do it in a commit-msg hook. This is because the user could still
|
7
|
+
# edit the message after a prepare-commit-msg hook was run.
|
8
|
+
class GerritChangeId < Base
|
9
|
+
SCRIPT_LOCATION = Overcommit::Utils.script_path('gerrit-change-id')
|
10
|
+
|
11
|
+
def run
|
12
|
+
result = execute([SCRIPT_LOCATION, commit_message_file])
|
13
|
+
return :pass if result.success?
|
14
|
+
|
15
|
+
[:fail, result.stdout]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Overcommit::Hook::CommitMsg
|
2
|
+
# Checks for hard tabs in commit messages.
|
3
|
+
class HardTabs < Base
|
4
|
+
def run
|
5
|
+
# Catches hard tabs entered by the user (not auto-generated)
|
6
|
+
if commit_message.index(/\t/)
|
7
|
+
return :warn, "Don't use hard tabs in commit messages"
|
8
|
+
end
|
9
|
+
|
10
|
+
:pass
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Overcommit::Hook::CommitMsg
|
2
|
+
# Checks for long commit messages (not good or bad--just fun to point out)
|
3
|
+
class RussianNovel < Base
|
4
|
+
RUSSIAN_NOVEL_LENGTH = 30
|
5
|
+
|
6
|
+
def run
|
7
|
+
if commit_message_lines.length >= RUSSIAN_NOVEL_LENGTH
|
8
|
+
return :warn, 'You seem to have authored a Russian novel; congratulations!'
|
9
|
+
end
|
10
|
+
|
11
|
+
:pass
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Overcommit::Hook::CommitMsg
|
2
|
+
# Ensures commit message subject lines are followed by a blank line.
|
3
|
+
class SingleLineSubject < Base
|
4
|
+
def run
|
5
|
+
unless commit_message_lines[1].to_s.strip.empty?
|
6
|
+
return :warn, 'Subject should be one line and followed by a blank line'
|
7
|
+
end
|
8
|
+
|
9
|
+
:pass
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Overcommit::Hook::CommitMsg
|
2
|
+
# Ensures the number of columns the subject and commit message lines occupy is
|
3
|
+
# under the preferred limits.
|
4
|
+
class TextWidth < Base
|
5
|
+
def run
|
6
|
+
@errors = []
|
7
|
+
|
8
|
+
find_errors_in_subject(commit_message_lines.first)
|
9
|
+
find_errors_in_body(commit_message_lines)
|
10
|
+
|
11
|
+
return :warn, @errors.join("\n") if @errors.any?
|
12
|
+
|
13
|
+
:pass
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def find_errors_in_subject(subject)
|
19
|
+
max_subject_width = config['max_subject_width']
|
20
|
+
return unless subject.length > max_subject_width
|
21
|
+
|
22
|
+
@errors << "Please keep the subject <= #{max_subject_width} characters"
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_errors_in_body(lines)
|
26
|
+
return unless lines.count > 2
|
27
|
+
|
28
|
+
max_body_width = config['max_body_width']
|
29
|
+
|
30
|
+
lines[2..-1].each_with_index do |line, index|
|
31
|
+
if line.chomp.size > max_body_width
|
32
|
+
@errors << "Line #{index + 3} of commit message has > " \
|
33
|
+
"#{max_body_width} characters"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Overcommit::Hook::CommitMsg
|
2
|
+
# Ensures commit message subject lines do not have a trailing period
|
3
|
+
class TrailingPeriod < Base
|
4
|
+
def run
|
5
|
+
if commit_message_lines.first.rstrip.end_with?('.')
|
6
|
+
return :warn, 'Please omit trailing period from commit message subject'
|
7
|
+
end
|
8
|
+
|
9
|
+
:pass
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Overcommit::Hook::PostCheckout
|
4
|
+
# Functionality common to all post-checkout hooks.
|
5
|
+
class Base < Overcommit::Hook::Base
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@context,
|
9
|
+
:previous_head, :new_head, :branch_checkout?, :file_checkout?
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Overcommit::Hook::PostCheckout
|
2
|
+
# Scans source code each time HEAD changes to generate an up-to-date index of
|
3
|
+
# all function/variable definitions, etc.
|
4
|
+
class IndexTags < Base
|
5
|
+
def run
|
6
|
+
unless in_path?('ctags')
|
7
|
+
return :pass # Silently ignore
|
8
|
+
end
|
9
|
+
|
10
|
+
index_tags_in_background
|
11
|
+
|
12
|
+
:pass
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
SCRIPT_LOCATION = Overcommit::Utils.script_path('index-tags')
|
18
|
+
|
19
|
+
def index_tags_in_background
|
20
|
+
ctags_args = config['ctags_arguments']
|
21
|
+
|
22
|
+
# TODO: come up with Ruby 1.8-friendly way to do this
|
23
|
+
Process.detach(Process.spawn("#{SCRIPT_LOCATION} #{ctags_args}"))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Overcommit::Hook::PostCommit
|
4
|
+
# Functionality common to all post-commit hooks.
|
5
|
+
class Base < Overcommit::Hook::Base
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@context, :modified_files_last_commit,
|
9
|
+
:modified_lines_in_file_last_commit
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Checks the format of an author's email address.
|
3
|
+
class AuthorEmail < Base
|
4
|
+
def run
|
5
|
+
result = execute(%w[git config --get user.email])
|
6
|
+
email = result.stdout.chomp
|
7
|
+
|
8
|
+
unless email =~ /#{config['pattern']}/
|
9
|
+
return :fail,
|
10
|
+
"Author has an invalid email address: '#{email}'\n" \
|
11
|
+
'Set your email with ' \
|
12
|
+
'`git config --global user.email your_email@example.com`'
|
13
|
+
end
|
14
|
+
|
15
|
+
:pass
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Ensures that a commit author has a name with at least first and last names.
|
3
|
+
class AuthorName < Base
|
4
|
+
def run
|
5
|
+
result = execute(%w[git config --get user.name])
|
6
|
+
name = result.stdout.chomp
|
7
|
+
|
8
|
+
unless name.split(' ').count >= 2
|
9
|
+
return :fail,
|
10
|
+
"Author must have at least first and last name, but was: #{name}." \
|
11
|
+
"\nSet your name with `git config --global user.name 'Your Name'`"
|
12
|
+
end
|
13
|
+
|
14
|
+
:pass
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Overcommit::Hook::PreCommit
|
4
|
+
# Functionality common to all pre-commit hooks.
|
5
|
+
class Base < Overcommit::Hook::Base
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@context, :modified_lines_in_file
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# Extract file, line number, and type of message from an error/warning
|
13
|
+
# messages in output.
|
14
|
+
#
|
15
|
+
# Assumes each element of `output` is a separate error/warning with all
|
16
|
+
# information necessary to identify it.
|
17
|
+
#
|
18
|
+
# @param output_messages [Array<String>] unprocessed error/warning messages
|
19
|
+
# @param regex [Regexp] regular expression defining `file`, `line` and
|
20
|
+
# `type` capture groups used to extract file locations and error/warning
|
21
|
+
# type from each line of output
|
22
|
+
# @param type_categorizer [Proc] function executed against the `type`
|
23
|
+
# capture group to convert it to a `:warning` or `:error` symbol. Assumes
|
24
|
+
# `:error` if `nil`.
|
25
|
+
# @raise [RuntimeError] line of output did not match regex
|
26
|
+
# @return [Array<Message>]
|
27
|
+
def extract_messages(output_messages, regex, type_categorizer = nil)
|
28
|
+
output_messages.map do |message|
|
29
|
+
unless match = message.match(regex)
|
30
|
+
raise 'Unexpected output: unable to determine line number or type ' \
|
31
|
+
"of error/warning for message '#{message}'"
|
32
|
+
end
|
33
|
+
|
34
|
+
file = extract_file(match, message)
|
35
|
+
line = extract_line(match, message)
|
36
|
+
type = extract_type(match, message, type_categorizer)
|
37
|
+
|
38
|
+
Overcommit::Hook::Message.new(type, file, line, message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def extract_file(match, message)
|
43
|
+
if match[:file].nil? || match[:file].empty?
|
44
|
+
raise "Unexpected output: no file found in '#{message}'"
|
45
|
+
end
|
46
|
+
|
47
|
+
match[:file]
|
48
|
+
end
|
49
|
+
|
50
|
+
def extract_line(match, message)
|
51
|
+
Integer(match[:line])
|
52
|
+
rescue ArgumentError, TypeError
|
53
|
+
raise "Unexpected output: invalid line number found in '#{message}'"
|
54
|
+
end
|
55
|
+
|
56
|
+
def extract_type(match, message, type_categorizer)
|
57
|
+
if type_categorizer
|
58
|
+
type_match = match.names.include?('type') ? match[:type] : nil
|
59
|
+
type = type_categorizer.call(type_match)
|
60
|
+
unless Overcommit::Hook::MESSAGE_TYPES.include?(type)
|
61
|
+
raise "Invalid message type '#{type}' for '#{message}': must " \
|
62
|
+
"be one of #{Overcommit::Hook::MESSAGE_TYPES.inspect}"
|
63
|
+
end
|
64
|
+
type
|
65
|
+
else
|
66
|
+
:error # Assume error since no categorizer was defined
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|