overcommit 0.22.0 → 0.23.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +169 -41
  3. data/lib/overcommit/configuration.rb +0 -2
  4. data/lib/overcommit/git_repo.rb +10 -3
  5. data/lib/overcommit/hook/base.rb +4 -0
  6. data/lib/overcommit/hook/post_checkout/index_tags.rb +2 -19
  7. data/lib/overcommit/hook/post_commit/base.rb +10 -0
  8. data/lib/overcommit/hook/post_commit/git_guilt.rb +39 -0
  9. data/lib/overcommit/hook/post_commit/index_tags.rb +9 -0
  10. data/lib/overcommit/hook/post_merge/base.rb +10 -0
  11. data/lib/overcommit/hook/post_merge/index_tags.rb +9 -0
  12. data/lib/overcommit/hook/post_rewrite/base.rb +10 -0
  13. data/lib/overcommit/hook/post_rewrite/index_tags.rb +12 -0
  14. data/lib/overcommit/hook/pre_commit/css_lint.rb +20 -2
  15. data/lib/overcommit/hook/pre_commit/es_lint.rb +18 -0
  16. data/lib/overcommit/hook/pre_commit/html_tidy.rb +35 -0
  17. data/lib/overcommit/hook/pre_commit/image_optim.rb +1 -1
  18. data/lib/overcommit/hook/pre_commit/java_checkstyle.rb +19 -0
  19. data/lib/overcommit/hook/pre_commit/js_hint.rb +9 -3
  20. data/lib/overcommit/hook/pre_commit/pep257.rb +19 -0
  21. data/lib/overcommit/hook/pre_commit/pep8.rb +19 -0
  22. data/lib/overcommit/hook/pre_commit/pyflakes.rb +28 -0
  23. data/lib/overcommit/hook/pre_commit/pylint.rb +28 -0
  24. data/lib/overcommit/hook/pre_commit/python_flake8.rb +18 -1
  25. data/lib/overcommit/hook/pre_commit/scalastyle.rb +26 -0
  26. data/lib/overcommit/hook/pre_commit/semi_standard.rb +17 -0
  27. data/lib/overcommit/hook/pre_commit/standard.rb +17 -0
  28. data/lib/overcommit/hook/pre_commit/w3c_css.rb +77 -0
  29. data/lib/overcommit/hook/pre_commit/w3c_html.rb +74 -0
  30. data/lib/overcommit/hook/pre_commit/xml_lint.rb +20 -0
  31. data/lib/overcommit/hook_context/post_commit.rb +31 -0
  32. data/lib/overcommit/hook_context/post_merge.rb +35 -0
  33. data/lib/overcommit/hook_context/post_rewrite.rb +18 -0
  34. data/lib/overcommit/hook_context/run_all.rb +12 -9
  35. data/lib/overcommit/utils.rb +25 -6
  36. data/lib/overcommit/version.rb +1 -1
  37. data/template-dir/hooks/post-commit +81 -0
  38. data/template-dir/hooks/post-merge +81 -0
  39. data/template-dir/hooks/post-rewrite +81 -0
  40. metadata +48 -10
  41. data/lib/overcommit/hook/pre_commit/jsx_hint.rb +0 -13
  42. data/lib/overcommit/hook/pre_commit/jsxcs.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: be12e52142407d34b856e8cf7c3b9e1743f9318b
4
- data.tar.gz: cbbf986c4d3e2a45d26b281e9716de2ef15cd2c2
3
+ metadata.gz: cc7753466602537df2c08569c1758136eec9f90b
4
+ data.tar.gz: 67ed7c78239ba382a78e9f6f976ec113dc4bff67
5
5
  SHA512:
6
- metadata.gz: 9ccfb37216d910e8c14b7d935c42a74b2ab372016bfe2b3e8eee4f63195028db62d34dbedec808d9b704d49f75991951eeabcdc3a857bbddccd8ebd55c4f00ee
7
- data.tar.gz: 2fe6b8c2563e6f709e7d844f4055386fd8a60f4239e82dedf9792b8efeb59d46ecf761c4f2c28998d1628cab1452c35cb125226090c29e35359776ebf83bbfe0
6
+ metadata.gz: 28bba28fd0dae45783ff7c43a7d0b847547b2680e7b900569d5d4b8ba8ef0c831ae3db30391154e7e04b100fcd2818e7b66ca7ed2ef247a035a0ffccf54b85cd
7
+ data.tar.gz: d7fb90d9cb74df2e57deea38fabadba464328ac8f1b445847c6c51ad7fa8a7f542c338f92d0ae1d7d115a21fdea0f9f191d94d6d3efa222d96f2567edb7e1b69
data/config/default.yml CHANGED
@@ -14,16 +14,36 @@ plugin_directory: '.git-hooks'
14
14
  # See https://github.com/causes/overcommit#security for more information.
15
15
  verify_plugin_signatures: true
16
16
 
17
- # Hooks that run after HEAD changes or a file is explicitly checked out. Useful
18
- # for updating source tags (e.g. via ctags) or warning about new migrations,
19
- # etc.
20
- PostCheckout:
17
+ # Hooks that are run against every commit message after a user has written it.
18
+ # These hooks are useful for enforcing policies on commit messages written for a
19
+ # project.
20
+ CommitMsg:
21
21
  ALL:
22
- required: false
22
+ requires_files: false
23
23
  quiet: false
24
- IndexTags:
24
+
25
+ GerritChangeId:
25
26
  enabled: false
26
- description: 'Generating tags file from source'
27
+ description: 'Ensuring Gerrit Change-Id is present'
28
+ required: true
29
+
30
+ HardTabs:
31
+ description: 'Checking for hard tabs'
32
+
33
+ RussianNovel:
34
+ description: 'Checking length of commit message'
35
+ quiet: true
36
+
37
+ SingleLineSubject:
38
+ description: 'Checking subject line'
39
+
40
+ TextWidth:
41
+ description: 'Checking text width'
42
+ max_subject_width: 60
43
+ max_body_width: 72
44
+
45
+ TrailingPeriod:
46
+ description: 'Checking for trailing periods in subject'
27
47
 
28
48
  # Hooks that are run after `git commit` is executed, before the commit message
29
49
  # editor is displayed. These hooks are ideal for syntax checkers, linters, and
@@ -105,6 +125,13 @@ PreCommit:
105
125
  install_command: 'npm install -g csslint'
106
126
  include: '**/*.css'
107
127
 
128
+ EsLint:
129
+ description: 'Analyzing with ESLint'
130
+ required_executable: 'eslint'
131
+ flags: ['--format=compact']
132
+ install_command: 'npm install -g eslint'
133
+ include: '**/*.js'
134
+
108
135
  GoLint:
109
136
  description: 'Analyzing with golint'
110
137
  required_executable: 'golint'
@@ -127,6 +154,13 @@ PreCommit:
127
154
  - '**/Makefile'
128
155
  - '.gitmodules'
129
156
 
157
+ HtmlTidy:
158
+ enabled: false
159
+ description: 'Analyzing HTML with tidy'
160
+ required_executable: 'tidy'
161
+ flags: ['-errors', '-quiet', '-utf8']
162
+ include: '**/*.html'
163
+
130
164
  ImageOptim:
131
165
  description: 'Checking for optimizable images'
132
166
  include:
@@ -135,6 +169,12 @@ PreCommit:
135
169
  - '**/*.jpeg'
136
170
  - '**/*.png'
137
171
 
172
+ JavaCheckstyle:
173
+ description: 'Analyzing with checkstyle'
174
+ required_executable: 'checkstyle'
175
+ flags: ['-c', '/sun_checks.xml']
176
+ include: '**/*.java'
177
+
138
178
  Jscs:
139
179
  description: 'Analyzing with JSCS'
140
180
  required_executable: 'jscs'
@@ -142,16 +182,10 @@ PreCommit:
142
182
  install_command: 'npm install -g jscs'
143
183
  include: '**/*.js'
144
184
 
145
- Jsxcs:
146
- description: 'Analyzing with JSXCS'
147
- required_executable: 'jsxcs'
148
- flags: ['--reporter=inline']
149
- install_command: 'npm install -g jsxcs'
150
- include: '**/*.jsx'
151
-
152
185
  JsHint:
153
186
  description: 'Analyzing with JSHint'
154
187
  required_executable: 'jshint'
188
+ flags: ['--verbose']
155
189
  install_command: 'npm install -g jshint'
156
190
  include: '**/*.js'
157
191
 
@@ -159,12 +193,6 @@ PreCommit:
159
193
  description: 'Validating JSON syntax'
160
194
  include: '**/*.json'
161
195
 
162
- JsxHint:
163
- description: 'Analyzing with JSXHint'
164
- required_executable: 'jsxhint'
165
- install_command: 'npm install -g jsxhint'
166
- include: '**/*.jsx'
167
-
168
196
  LocalPathsInGemfile:
169
197
  description: 'Checking for local paths in Gemfile'
170
198
  required_executable: 'grep'
@@ -177,6 +205,19 @@ PreCommit:
177
205
  required_executable: 'grep'
178
206
  flags: ['-IHn', '^<<<<<<<\s']
179
207
 
208
+ Pep257:
209
+ description: 'Analyzing docstrings with pep257'
210
+ required_executable: 'pep257'
211
+ install_command: 'pip install pep257'
212
+ include: '**/*.py'
213
+
214
+ Pep8:
215
+ enabled: false
216
+ description: 'Analyzing with pep8'
217
+ required_executable: 'pep8'
218
+ install_command: 'pip install pep8'
219
+ include: '**/*.py'
220
+
180
221
  PryBinding:
181
222
  description: 'Checking for instances of binding.pry'
182
223
  quiet: true
@@ -184,6 +225,23 @@ PreCommit:
184
225
  - '**/*.rb'
185
226
  - '**/*.rake'
186
227
 
228
+ Pyflakes:
229
+ enabled: false
230
+ description: 'Analyzing with pyflakes'
231
+ required_executable: 'pyflakes'
232
+ install_command: 'pip install pyflakes'
233
+ include: '**/*.py'
234
+
235
+ Pylint:
236
+ description: 'Analyzing with Pylint'
237
+ required_executable: 'pylint'
238
+ install_command: 'pip install pylint'
239
+ flags:
240
+ - '--msg-template="{path}:{line}:{C}: {msg} ({symbol})"'
241
+ - '--reports=n'
242
+ - '--persistent=n'
243
+ include: '**/*.py'
244
+
187
245
  PythonFlake8:
188
246
  description: 'Analyzing with flake8'
189
247
  required_executable: 'flake8'
@@ -222,18 +280,39 @@ PreCommit:
222
280
  - '**/Gemfile'
223
281
  - '**/Rakefile'
224
282
 
283
+ Scalastyle:
284
+ description: 'Analyzing with Scalastyle'
285
+ required_executable: 'scalastyle'
286
+ include: '**/*.scala'
287
+
225
288
  ScssLint:
226
289
  description: 'Analyzing with scss-lint'
227
290
  required_executable: 'scss-lint'
228
291
  install_command: 'gem install scss-lint'
229
292
  include: '**/*.scss'
230
293
 
294
+ SemiStandard:
295
+ enabled: false
296
+ description: 'Analyzing with semistandard'
297
+ required_executable: 'semistandard'
298
+ flags: ['--verbose']
299
+ install_command: 'npm install -g semistandard'
300
+ include: '**/*.js'
301
+
231
302
  ShellCheck:
232
303
  description: 'Analyzing with ShellCheck'
233
304
  required_executable: 'shellcheck'
234
305
  flags: ['--format=gcc']
235
306
  include: '**/*.sh'
236
307
 
308
+ Standard:
309
+ enabled: false
310
+ description: 'Analyzing with standard'
311
+ required_executable: 'standard'
312
+ flags: ['--verbose']
313
+ install_command: 'npm install -g standard'
314
+ include: '**/*.js'
315
+
237
316
  TrailingWhitespace:
238
317
  description: 'Checking for trailing whitespace'
239
318
  required_executable: 'grep'
@@ -248,37 +327,86 @@ PreCommit:
248
327
  install_command: 'gem install travis'
249
328
  include: '.travis.yml'
250
329
 
330
+ W3cCss:
331
+ enabled: false
332
+ description: 'Analyzing with W3C CSS validation service'
333
+ validator_uri: 'http://jigsaw.w3.org/css-validator/validator'
334
+ language: 'en'
335
+ profile: 'css3'
336
+ warn_level: 2
337
+ include:
338
+ - '**/*.css'
339
+
340
+ W3cHtml:
341
+ enabled: false
342
+ description: 'Analyzing with W3C HTML validation service'
343
+ validator_uri: 'http://validator.w3.org/check'
344
+ charset: 'utf-8'
345
+ doctype: 'HTML5'
346
+ include:
347
+ - '**/*.html'
348
+
349
+ XmlLint:
350
+ description: 'Analyzing with xmllint'
351
+ required_executable: 'xmllint'
352
+ flags: ['--noout']
353
+ include: '**/*.xml'
354
+
251
355
  YamlSyntax:
252
356
  description: 'Checking YAML syntax'
253
- include: '**/*.yml'
357
+ include:
358
+ - '**/*.yaml'
359
+ - '**/*.yml'
254
360
 
255
- # Hooks that are run against every commit message after a user has written it.
256
- # These hooks are useful for enforcing policies on commit messages written for a
257
- # project.
258
- CommitMsg:
361
+ # Hooks that run after HEAD changes or a file is explicitly checked out.
362
+ PostCheckout:
363
+ ALL:
364
+ required: false
365
+ quiet: false
366
+
367
+ IndexTags:
368
+ enabled: false
369
+ description: 'Generating tags file from source'
370
+ required_executable: 'ctags'
371
+
372
+ # Hooks that run after a commit is created.
373
+ PostCommit:
259
374
  ALL:
260
375
  requires_files: false
376
+ required: false
261
377
  quiet: false
262
378
 
263
- GerritChangeId:
379
+ GitGuilt:
264
380
  enabled: false
265
- description: 'Ensuring Gerrit Change-Id is present'
266
- required: true
381
+ description: 'Calculating changes in blame since last commit'
382
+ requires_files: true
383
+ required_executable: 'git-guilt'
384
+ flags: ['HEAD~', 'HEAD']
385
+ install_command: 'npm install -g git-guilt'
267
386
 
268
- HardTabs:
269
- description: 'Checking for hard tabs'
387
+ IndexTags:
388
+ enabled: false
389
+ description: 'Generating tags file from source'
390
+ required_executable: 'ctags'
270
391
 
271
- RussianNovel:
272
- description: 'Checking length of commit message'
273
- quiet: true
392
+ # Hooks that run after `git merge` executes successfully (no merge conflicts).
393
+ PostMerge:
394
+ ALL:
395
+ requires_files: false
396
+ quiet: false
274
397
 
275
- SingleLineSubject:
276
- description: 'Checking subject line'
398
+ IndexTags:
399
+ enabled: false
400
+ description: 'Generating tags file from source'
401
+ required_executable: 'ctags'
277
402
 
278
- TextWidth:
279
- description: 'Checking text width'
280
- max_subject_width: 60
281
- max_body_width: 72
403
+ # Hooks that run after a commit is modified by an amend or rebase.
404
+ PostRewrite:
405
+ ALL:
406
+ requires_files: false
407
+ quiet: false
282
408
 
283
- TrailingPeriod:
284
- description: 'Checking for trailing periods in subject'
409
+ IndexTags:
410
+ enabled: false
411
+ description: 'Generating tags file from source'
412
+ required_executable: 'ctags'
@@ -170,8 +170,6 @@ module Overcommit
170
170
  def smart_merge(parent, child)
171
171
  parent.merge(child) do |_key, old, new|
172
172
  case old
173
- when Array
174
- old + Array(new)
175
173
  when Hash
176
174
  smart_merge(old, new)
177
175
  else
@@ -20,8 +20,10 @@ module Overcommit
20
20
  lines = Set.new
21
21
 
22
22
  flags = '--cached' if options[:staged]
23
+ refs = options[:refs]
24
+ subcmd = options[:subcmd] || 'diff'
23
25
 
24
- `git diff --no-ext-diff -U0 #{flags} -- #{file_path}`.
26
+ `git #{subcmd} --no-ext-diff -U0 #{flags} #{refs} -- '#{file_path}'`.
25
27
  scan(DIFF_HUNK_REGEX) do |start_line, lines_added|
26
28
  lines_added = (lines_added || 1).to_i # When blank, one line was added
27
29
  cur_line = start_line.to_i
@@ -42,9 +44,13 @@ module Overcommit
42
44
  # @return [Array<String>] list of absolute file paths
43
45
  def modified_files(options)
44
46
  flags = '--cached' if options[:staged]
47
+ refs = options[:refs]
48
+ subcmd = options[:subcmd] || 'diff'
45
49
 
46
- `git diff --name-only -z --diff-filter=ACM --ignore-submodules=all #{flags}`.
50
+ `git #{subcmd} --name-only -z --diff-filter=ACM --ignore-submodules=all #{flags} #{refs}`.
47
51
  split("\0").
52
+ map(&:strip).
53
+ reject(&:empty?).
48
54
  map { |relative_file| File.expand_path(relative_file) }
49
55
  end
50
56
 
@@ -54,7 +60,8 @@ module Overcommit
54
60
  def all_files
55
61
  `git ls-files`.
56
62
  split(/\n/).
57
- map { |relative_file| File.expand_path(relative_file) }
63
+ map { |relative_file| File.expand_path(relative_file) }.
64
+ reject { |file| File.directory?(file) } # Exclude submodule directories
58
65
  end
59
66
 
60
67
  # Returns whether the current git branch is empty (has no commits).
@@ -111,6 +111,10 @@ module Overcommit::Hook
111
111
  Overcommit::Utils.execute(cmd)
112
112
  end
113
113
 
114
+ def execute_in_background(cmd)
115
+ Overcommit::Utils.execute_in_background(cmd)
116
+ end
117
+
114
118
  def required_executable
115
119
  @config['required_executable']
116
120
  end
@@ -1,26 +1,9 @@
1
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.
2
+ # Updates ctags index for all source code in the repository.
4
3
  class IndexTags < Base
5
4
  def run
6
- unless in_path?('ctags')
7
- return :pass # Silently ignore
8
- end
9
-
10
- index_tags_in_background
11
-
5
+ execute_in_background([Overcommit::Utils.script_path('index-tags')])
12
6
  :pass
13
7
  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
8
  end
26
9
  end
@@ -0,0 +1,10 @@
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_lines_in_file, :initial_commit?
9
+ end
10
+ end
@@ -0,0 +1,39 @@
1
+ module Overcommit::Hook::PostCommit
2
+ # Calculates the change in blame since the last revision.
3
+ class GitGuilt < Base
4
+ PLUS_MINUS_REGEX = /^(.*?)(?:(\++)|(-+))$/
5
+ GREEN = 32
6
+ RED = 31
7
+
8
+ def run
9
+ return :pass if initial_commit?
10
+ result = execute(command)
11
+ return :fail, result.stderr unless result.success?
12
+
13
+ return :pass if result.stdout.strip.empty?
14
+
15
+ output = []
16
+ result.stdout.scan(PLUS_MINUS_REGEX) do |user, plus, minus|
17
+ plus = color(GREEN, plus)
18
+ minus = color(RED, minus)
19
+ output << "#{user}#{plus}#{minus}"
20
+ end
21
+
22
+ [:warn, output.join("\n")]
23
+ end
24
+
25
+ private
26
+
27
+ # Returns text wrapped in ANSI escape code necessary to produce a given
28
+ # color/text display.
29
+ #
30
+ # Taken from Overcommit::Logger as a temporary workaround.
31
+ # TODO: expose logger instance to hooks for colorized output
32
+ #
33
+ # @param code [String] ANSI escape code, e.g. '1;33' for "bold yellow"
34
+ # @param str [String] string to wrap
35
+ def color(code, str)
36
+ STDOUT.tty? ? "\033[#{code}m#{str}\033[0m" : str
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ module Overcommit::Hook::PostCommit
2
+ # Updates ctags index for all source code in the repository.
3
+ class IndexTags < Base
4
+ def run
5
+ execute_in_background([Overcommit::Utils.script_path('index-tags')])
6
+ :pass
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'forwardable'
2
+
3
+ module Overcommit::Hook::PostMerge
4
+ # Functionality common to all post-merge hooks.
5
+ class Base < Overcommit::Hook::Base
6
+ extend Forwardable
7
+
8
+ def_delegators :@context, :modified_lines_in_file, :squash?, :merge_commit?
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Overcommit::Hook::PostMerge
2
+ # Updates ctags index for all source code in the repository.
3
+ class IndexTags < Base
4
+ def run
5
+ execute_in_background([Overcommit::Utils.script_path('index-tags')])
6
+ :pass
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'forwardable'
2
+
3
+ module Overcommit::Hook::PostRewrite
4
+ # Functionality common to all post-rewrite hooks.
5
+ class Base < Overcommit::Hook::Base
6
+ extend Forwardable
7
+
8
+ def_delegators :@context, :amend?, :rebase?
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module Overcommit::Hook::PostRewrite
2
+ # Updates ctags index for all source code in the repository.
3
+ class IndexTags < Base
4
+ def run
5
+ # Ignore unless this is a rebase (amends are covered by post-commit hook)
6
+ return :pass unless rebase?
7
+
8
+ execute_in_background([Overcommit::Utils.script_path('index-tags')])
9
+ :pass
10
+ end
11
+ end
12
+ end
@@ -1,11 +1,29 @@
1
1
  module Overcommit::Hook::PreCommit
2
2
  # Runs `csslint` against any modified CSS files.
3
3
  class CssLint < Base
4
+ MESSAGE_REGEX = /
5
+ ^(?<file>[^:]+):\s
6
+ (?:line\s(?<line>\d+)[^EW]+)?
7
+ (?<type>Error|Warning)
8
+ /x
9
+
4
10
  def run
5
11
  result = execute(command + applicable_files)
6
- return :pass if result.stdout !~ /Error - (?!Unknown @ rule)/
12
+ output = result.stdout.chomp
13
+ return :pass if result.success? && output.empty?
14
+
15
+ extract_messages(
16
+ output.split("\n").collect(&method(:add_line_number)),
17
+ MESSAGE_REGEX,
18
+ lambda { |type| type.downcase.to_sym }
19
+ )
20
+ end
21
+
22
+ private
7
23
 
8
- [:fail, result.stdout]
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')
9
27
  end
10
28
  end
11
29
  end
@@ -0,0 +1,18 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `eslint` against any modified JavaScript files.
3
+ class EsLint < Base
4
+ def run
5
+ result = execute(command + applicable_files)
6
+ output = result.stdout.chomp
7
+ return :pass if result.success? && output.empty?
8
+
9
+ # example message:
10
+ # path/to/file.js: line 1, col 0, Error - Error message (ruleName)
11
+ extract_messages(
12
+ output.split("\n").grep(/Warning|Error/),
13
+ /^(?<file>[^:]+):[^\d]+(?<line>\d+).*?(?<type>Error|Warning)/,
14
+ lambda { |type| type.downcase.to_sym }
15
+ )
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `tidy` against any modified HTML files.
3
+ class HtmlTidy < Base
4
+ MESSAGE_REGEX = /
5
+ ^(?<file>[^:]+):\s
6
+ line\s(?<line>\d+)\s
7
+ column\s(?<col>\d+)\s-\s
8
+ (?<type>Error|Warning):\s(?<message>.+)$
9
+ /x
10
+
11
+ def run
12
+ # example message:
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
+ applicable_files.collect do |file|
25
+ result = execute(command + [file])
26
+ output = result.stderr.chomp
27
+ extract_messages(
28
+ output.split("\n").collect { |msg| "#{file}: #{msg}" },
29
+ MESSAGE_REGEX,
30
+ lambda { |type| type.downcase.to_sym }
31
+ )
32
+ end.flatten
33
+ end
34
+ end
35
+ end
@@ -5,7 +5,7 @@ module Overcommit::Hook::PreCommit
5
5
  begin
6
6
  require 'image_optim'
7
7
  rescue LoadError
8
- return :warn, 'image_optim not installed -- run `gem install image_optim`'
8
+ return :fail, 'image_optim not installed -- run `gem install image_optim`'
9
9
  end
10
10
 
11
11
  optimized_images =
@@ -0,0 +1,19 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `checkstyle` against any modified Java files.
3
+ class JavaCheckstyle < Base
4
+ MESSAGE_REGEX = /^(?<file>[^:]+):(?<line>\d+)/
5
+
6
+ def run
7
+ result = execute(command + applicable_files)
8
+ output = result.stdout.chomp
9
+ return :pass if result.success?
10
+
11
+ # example message:
12
+ # path/to/file.java:3:5: Error message
13
+ extract_messages(
14
+ output.split("\n").grep(MESSAGE_REGEX),
15
+ MESSAGE_REGEX
16
+ )
17
+ end
18
+ end
19
+ end
@@ -3,11 +3,17 @@ module Overcommit::Hook::PreCommit
3
3
  class JsHint < Base
4
4
  def run
5
5
  result = execute(command + applicable_files)
6
- output = result.stdout
6
+ output = result.stdout.chomp
7
7
 
8
- return :pass if output.empty?
8
+ return :pass if result.success? && output.empty?
9
9
 
10
- [:fail, output]
10
+ # example message:
11
+ # path/to/file.js: line 1, col 0, Error message (E001)
12
+ extract_messages(
13
+ output.split("\n").grep(/E|W/),
14
+ /^(?<file>[^:]+):[^\d]+(?<line>\d+).+\((?<type>E|W)\d+\)/,
15
+ lambda { |type| type.include?('W') ? :warning : :error }
16
+ )
11
17
  end
12
18
  end
13
19
  end
@@ -0,0 +1,19 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `pep257` against any modified Python files.
3
+ class Pep257 < Base
4
+ def run
5
+ result = execute(command + applicable_files)
6
+ return :pass if result.success?
7
+
8
+ output = result.stderr.chomp
9
+
10
+ # example message:
11
+ # path/to/file.py:1 in public method `foo`:
12
+ # D102: Docstring missing
13
+ extract_messages(
14
+ output.gsub(/:\s+/, ': ').split("\n"),
15
+ /^(?<file>[^:]+):(?<line>\d+)/
16
+ )
17
+ end
18
+ end
19
+ end