overcommit 0.5.0 → 0.6.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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/bin/overcommit +3 -4
  3. data/config/default.yml +139 -0
  4. data/lib/overcommit.rb +7 -5
  5. data/lib/overcommit/cli.rb +59 -64
  6. data/lib/overcommit/configuration.rb +108 -34
  7. data/lib/overcommit/configuration_loader.rb +47 -0
  8. data/lib/overcommit/constants.rb +7 -0
  9. data/lib/overcommit/exceptions.rb +16 -0
  10. data/lib/overcommit/hook/base.rb +91 -0
  11. data/lib/overcommit/hook/commit_msg/base.rb +11 -0
  12. data/lib/overcommit/hook/commit_msg/gerrit_change_id.rb +18 -0
  13. data/lib/overcommit/{plugins → hook}/commit_msg/hard_tabs.rb +5 -6
  14. data/lib/overcommit/hook/commit_msg/russian_novel.rb +14 -0
  15. data/lib/overcommit/hook/commit_msg/single_line_subject.rb +12 -0
  16. data/lib/overcommit/hook/commit_msg/text_width.rb +20 -0
  17. data/lib/overcommit/hook/commit_msg/trailing_period.rb +12 -0
  18. data/lib/overcommit/hook/post_checkout/base.rb +11 -0
  19. data/lib/overcommit/hook/post_checkout/bundle_check.rb +29 -0
  20. data/lib/overcommit/hook/post_checkout/index_tags.rb +24 -0
  21. data/lib/overcommit/hook/pre_commit/author_email.rb +17 -0
  22. data/lib/overcommit/hook/pre_commit/author_name.rb +17 -0
  23. data/lib/overcommit/hook/pre_commit/base.rb +10 -0
  24. data/lib/overcommit/hook/pre_commit/bundle_check.rb +30 -0
  25. data/lib/overcommit/hook/pre_commit/coffee_lint.rb +14 -0
  26. data/lib/overcommit/hook/pre_commit/css_lint.rb +16 -0
  27. data/lib/overcommit/hook/pre_commit/haml_lint.rb +26 -0
  28. data/lib/overcommit/hook/pre_commit/hard_tabs.rb +16 -0
  29. data/lib/overcommit/hook/pre_commit/image_optim.rb +41 -0
  30. data/lib/overcommit/hook/pre_commit/js_hint.rb +15 -0
  31. data/lib/overcommit/hook/pre_commit/jscs.rb +31 -0
  32. data/lib/overcommit/hook/pre_commit/python_flake8.rb +14 -0
  33. data/lib/overcommit/hook/pre_commit/rubocop.rb +26 -0
  34. data/lib/overcommit/hook/pre_commit/scss_lint.rb +26 -0
  35. data/lib/overcommit/hook/pre_commit/trailing_whitespace.rb +15 -0
  36. data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +22 -0
  37. data/lib/overcommit/hook_context.rb +16 -0
  38. data/lib/overcommit/hook_context/base.rb +68 -0
  39. data/lib/overcommit/hook_context/commit_msg.rb +32 -0
  40. data/lib/overcommit/hook_context/post_checkout.rb +24 -0
  41. data/lib/overcommit/hook_context/pre_commit.rb +96 -0
  42. data/lib/overcommit/hook_runner.rb +150 -0
  43. data/lib/overcommit/installer.rb +61 -68
  44. data/lib/overcommit/logger.rb +16 -13
  45. data/lib/overcommit/utils.rb +63 -38
  46. data/lib/overcommit/version.rb +1 -1
  47. data/{bin/scripts → libexec}/gerrit-change-id +0 -0
  48. data/{bin/scripts → libexec}/index-tags +1 -3
  49. data/template-dir/hooks/commit-msg +83 -0
  50. data/template-dir/hooks/overcommit-hook +83 -0
  51. data/template-dir/hooks/post-checkout +83 -0
  52. data/template-dir/hooks/pre-commit +83 -0
  53. metadata +76 -57
  54. data/bin/hooks/commit-msg +0 -8
  55. data/bin/hooks/post-checkout +0 -9
  56. data/bin/hooks/post-merge +0 -23
  57. data/bin/hooks/pre-commit +0 -8
  58. data/bin/hooks/prepare-commit-msg +0 -159
  59. data/bin/run-hook +0 -8
  60. data/bin/scripts/check-gemfile +0 -9
  61. data/bin/scripts/csslint-rhino.js +0 -9080
  62. data/bin/scripts/jshint.js +0 -5921
  63. data/bin/scripts/jshint_runner.js +0 -42
  64. data/lib/overcommit/errors.rb +0 -3
  65. data/lib/overcommit/git_hook.rb +0 -89
  66. data/lib/overcommit/hook_specific_check.rb +0 -110
  67. data/lib/overcommit/hooks/commit_msg.rb +0 -7
  68. data/lib/overcommit/hooks/pre_commit.rb +0 -9
  69. data/lib/overcommit/plugins/commit_msg/change_id.rb +0 -15
  70. data/lib/overcommit/plugins/commit_msg/release_note.rb +0 -25
  71. data/lib/overcommit/plugins/commit_msg/russian_novel.rb +0 -16
  72. data/lib/overcommit/plugins/commit_msg/single_line_subject.rb +0 -13
  73. data/lib/overcommit/plugins/commit_msg/text_width.rb +0 -20
  74. data/lib/overcommit/plugins/commit_msg/trailing_period.rb +0 -13
  75. data/lib/overcommit/plugins/pre_commit/author_name.rb +0 -16
  76. data/lib/overcommit/plugins/pre_commit/causes_email.rb +0 -15
  77. data/lib/overcommit/plugins/pre_commit/coffee_lint.rb +0 -16
  78. data/lib/overcommit/plugins/pre_commit/css_linter.rb +0 -17
  79. data/lib/overcommit/plugins/pre_commit/haml_style.rb +0 -34
  80. data/lib/overcommit/plugins/pre_commit/haml_syntax.rb +0 -24
  81. data/lib/overcommit/plugins/pre_commit/image_optimization.rb +0 -50
  82. data/lib/overcommit/plugins/pre_commit/js_console_log.rb +0 -16
  83. data/lib/overcommit/plugins/pre_commit/js_syntax.rb +0 -30
  84. data/lib/overcommit/plugins/pre_commit/python_flake8.rb +0 -15
  85. data/lib/overcommit/plugins/pre_commit/ruby_style.rb +0 -67
  86. data/lib/overcommit/plugins/pre_commit/ruby_syntax.rb +0 -19
  87. data/lib/overcommit/plugins/pre_commit/scss_lint.rb +0 -66
  88. data/lib/overcommit/plugins/pre_commit/test_history.rb +0 -58
  89. data/lib/overcommit/plugins/pre_commit/whitespace.rb +0 -21
  90. data/lib/overcommit/plugins/pre_commit/yaml_syntax.rb +0 -22
  91. data/lib/overcommit/reporter.rb +0 -90
  92. data/lib/overcommit/staged_file.rb +0 -86
@@ -1,34 +0,0 @@
1
- module Overcommit::GitHook
2
- class HamlStyle < HookSpecificCheck
3
- include HookRegistry
4
- file_types :haml
5
-
6
- def run_check
7
- unless in_path?('haml-lint')
8
- return :warn, 'haml-lint not installed -- run `gem install haml-lint`'
9
- end
10
-
11
- paths_to_staged_files = Hash[staged.map { |s| [s.path, s] }]
12
- staged_files = paths_to_staged_files.keys
13
-
14
- output = `haml-lint #{staged_files.join(' ')} 2>&1`
15
- return :good if $?.success?
16
-
17
- # Keep lines from the output for files that we actually modified
18
- error_lines, warning_lines = output.lines.partition do |output_line|
19
- if match = output_line.match(/^([^:]+):(\d+)/)
20
- file = match[1]
21
- line = match[2]
22
- end
23
- unless paths_to_staged_files[file]
24
- return :warn, "Unexpected output from haml-lint:\n#{output}"
25
- end
26
- paths_to_staged_files[file].modified_lines.include?(line.to_i)
27
- end
28
-
29
- return :bad, error_lines.join unless error_lines.empty?
30
- return :warn, "Modified files have lints (on lines you didn't modify)\n" <<
31
- warning_lines.join
32
- end
33
- end
34
- end
@@ -1,24 +0,0 @@
1
- module Overcommit::GitHook
2
- class HamlSyntax < HookSpecificCheck
3
- include HookRegistry
4
- file_type :haml
5
-
6
- def run_check
7
- begin
8
- require 'haml'
9
- rescue LoadError
10
- return :warn, "'haml' gem not installed -- run `gem install haml`"
11
- end
12
-
13
- staged.map { |s| s.path }.each do |path|
14
- begin
15
- Haml::Engine.new(File.read(path), :check_syntax => true)
16
- rescue Haml::Error => e
17
- return :bad, e.message
18
- end
19
- end
20
-
21
- :good
22
- end
23
- end
24
- end
@@ -1,50 +0,0 @@
1
- module Overcommit::GitHook
2
- class ImageOptimization < HookSpecificCheck
3
- include HookRegistry
4
- file_types :gif, :jpeg, :jpg, :png
5
-
6
- def run_check
7
- begin
8
- require 'image_optim'
9
- rescue LoadError
10
- return :warn, "'image_optim' gem not installed -- run `gem install image_optim`"
11
- end
12
-
13
- optimized_images =
14
- begin
15
- ImageSet.new(staged.map(&:original_path)).
16
- optimize_with(ImageOptim.new(:pngout => false))
17
-
18
- rescue ImageOptim::BinNotFoundError => e
19
- return :stop,
20
- "#{e.message}. The image_optim gem is dependendent on this binary. " <<
21
- "See https://github.com/toy/image_optim for more info."
22
- end
23
-
24
- if optimized_images.any?
25
- return :bad,
26
- "Optimized #{optimized_images.map(&:to_s).inspect}. " <<
27
- " Please add them to your commit."
28
- else
29
- return :good
30
- end
31
- end
32
-
33
- class ImageSet
34
- attr_reader :image_paths
35
-
36
- def initialize(image_paths)
37
- @image_paths ||= image_paths
38
- end
39
-
40
- def optimize_with(image_optim)
41
- results =
42
- image_optim.optimize_images!(image_paths) do |path, was_optimized|
43
- path if was_optimized
44
- end
45
-
46
- results.compact
47
- end
48
- end
49
- end
50
- end
@@ -1,16 +0,0 @@
1
- module Overcommit::GitHook
2
- class JSConsoleLog < HookSpecificCheck
3
- include HookRegistry
4
- file_type :js
5
-
6
- # https://www.pivotaltracker.com/story/show/18119495
7
- def run_check
8
- paths = staged.collect(&:path).join(' ')
9
- output = `grep -n -e 'console\\.log' #{paths}`.split("\n").reject do |line|
10
- /^\d+:\s*\/\// =~ line || # Skip comments
11
- /ALLOW_CONSOLE_LOG/ =~ line # and lines with ALLOW_CONSOLE_LOG
12
- end.join("\n")
13
- return (output.empty? ? :good : :bad), output
14
- end
15
- end
16
- end
@@ -1,30 +0,0 @@
1
- module Overcommit::GitHook
2
- class JSSyntax < HookSpecificCheck
3
- include HookRegistry
4
- file_type :js
5
-
6
- def run_check
7
- return :warn, 'Need either `jshint` or `rhino` in path' unless runner
8
-
9
- paths = staged.collect(&:path).join(' ')
10
- output = runner.call(paths)
11
-
12
- return (output.empty? ? :good : :bad), output
13
- end
14
-
15
- private
16
-
17
- JS_HINT_PATH = Overcommit::Utils.script_path 'jshint.js'
18
- JS_HINT_RUNNER_PATH = Overcommit::Utils.script_path 'jshint_runner.js'
19
-
20
- def runner
21
- if in_path? 'jshint'
22
- lambda { |paths| `jshint #{paths}` }
23
- elsif in_path? 'rhino'
24
- lambda do |paths|
25
- `rhino -strict -f #{JS_HINT_PATH} #{JS_HINT_RUNNER_PATH} #{paths} 2>&1 | grep -v warning | grep -v -e '^js: '`
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,15 +0,0 @@
1
- module Overcommit::GitHook
2
- class PythonFlake8 < HookSpecificCheck
3
- include HookRegistry
4
- file_type :py
5
-
6
- def run_check
7
- unless in_path? 'flake8'
8
- return :warn, 'Run `pip install flake8`'
9
- end
10
-
11
- output = `flake8 #{(staged.collect(&:path).join(' '))}`.split("\n")
12
- return ($?.success? ? :good : :bad), output
13
- end
14
- end
15
- end
@@ -1,67 +0,0 @@
1
- require 'enumerator'
2
- require 'pathname'
3
-
4
- module Overcommit::GitHook
5
- class RubyStyle < HookSpecificCheck
6
- include HookRegistry
7
- file_types :rb, :rake
8
-
9
- def run_check
10
- unless in_path?('rubocop')
11
- return :warn, 'rubocop not installed -- run `gem install rubocop`'
12
- end
13
-
14
- paths_to_staged_files = Hash[staged.map { |s| [s.path, s] }]
15
-
16
- success, output = run_rubocop
17
- return :good if success
18
-
19
- # Keep lines from the output for files that we actually modified
20
- error_lines, warning_lines = output.lines.partition do |output_line|
21
- if match = output_line.match(/^([^:]+):(\d+)/)
22
- file = match[1]
23
- line = match[2]
24
- end
25
- unless paths_to_staged_files[file]
26
- return :warn, "Unexpected output from rubocop:\n#{output}"
27
- end
28
- paths_to_staged_files[file].modified_lines.include?(line.to_i)
29
- end
30
-
31
- return :bad, error_lines.join unless error_lines.empty?
32
- return :warn, "Modified files have style lints (on lines you didn't modify)\n" <<
33
- warning_lines.join
34
- end
35
-
36
- private
37
-
38
- def run_rubocop
39
- success, output = true, ''
40
- rubocop_config_mapping.each do |config, files|
41
- config = config ? "-c #{config}" : ''
42
- output += `rubocop #{config} --format=emacs #{files.join(' ')} 2>&1`
43
- success = success && $?.success?
44
- end
45
- [success, output]
46
- end
47
-
48
- def rubocop_config_mapping
49
- staged.inject({}) do |mapping, file|
50
- config = rubocop_yml_for(file)
51
- mapping[config] ||= []
52
- mapping[config] << file.path
53
- mapping
54
- end
55
- end
56
-
57
- def rubocop_yml_for(staged_file)
58
- possible_files(staged_file.original_path).find { |path| path.file? }
59
- end
60
-
61
- def possible_files(file_path)
62
- files = Pathname.new(file_path).enum_for(:ascend).
63
- map { |path| path + '.rubocop.yml' }
64
- files << Pathname.new('.rubocop.yml')
65
- end
66
- end
67
- end
@@ -1,19 +0,0 @@
1
- module Overcommit::GitHook
2
- class RubySyntax < HookSpecificCheck
3
- include HookRegistry
4
- file_types :rb, :rake
5
-
6
- def run_check
7
- clean = true
8
- output = []
9
- staged.each do |staged|
10
- syntax = `ruby -c #{staged.path} 2>&1`
11
- unless $?.success?
12
- output += syntax.lines.to_a
13
- clean = false
14
- end
15
- end
16
- return (clean ? :good : :bad), output
17
- end
18
- end
19
- end
@@ -1,66 +0,0 @@
1
- module Overcommit::GitHook
2
- class ScssLint < HookSpecificCheck
3
- include HookRegistry
4
- file_type :scss
5
-
6
- def run_check
7
- begin
8
- require 'scss_lint'
9
- rescue LoadError
10
- return :warn, 'scss-lint not installed -- run `gem install scss-lint`'
11
- end
12
-
13
- paths_to_staged_files = Hash[staged.map { |s| [s.path, s] }]
14
-
15
- success, output = run_scss_lint
16
- return :good if success
17
-
18
- # Keep lines from the output for files that we actually modified
19
- error_lines, warning_lines = output.lines.partition do |output_line|
20
- if match = output_line.match(/^([^:]+):(\d+)/)
21
- file = match[1]
22
- line = match[2]
23
- end
24
- unless paths_to_staged_files[file]
25
- return :warn, "Unexpected output from scss-lint:\n#{output}"
26
- end
27
- paths_to_staged_files[file].modified_lines.include?(line.to_i)
28
- end
29
-
30
- return :bad, error_lines.join unless error_lines.empty?
31
- return :warn, "Modified files have lints (on lines you didn't modify)\n" <<
32
- warning_lines.join
33
- end
34
-
35
- private
36
-
37
- def run_scss_lint
38
- success, output = true, ''
39
- scss_lint_config_mapping.each do |config, files|
40
- config = config ? "-c #{config}" : ''
41
- output += `scss-lint #{config} #{files.join(' ')} 2>&1`
42
- success = success && $?.success?
43
- end
44
- [success, output]
45
- end
46
-
47
- def scss_lint_config_mapping
48
- staged.inject({}) do |mapping, file|
49
- config = scss_lint_yml_for(file)
50
- mapping[config] ||= []
51
- mapping[config] << file.path
52
- mapping
53
- end
54
- end
55
-
56
- def scss_lint_yml_for(staged_file)
57
- possible_files(staged_file.original_path).find { |path| path.file? }
58
- end
59
-
60
- def possible_files(file_path)
61
- files = Pathname.new(file_path).enum_for(:ascend).
62
- map { |path| path + '.scss-lint.yml' }
63
- files << Pathname.new('.scss-lint.yml')
64
- end
65
- end
66
- end
@@ -1,58 +0,0 @@
1
- module Overcommit::GitHook
2
- class TestHistory < HookSpecificCheck
3
- include HookRegistry
4
-
5
- def relevant_tests
6
- @relevant_test ||=
7
- `relevant-tests 2> /dev/null -- #{modified_files.join(' ')}`.
8
- split("\n").map { |r| File.expand_path r }
9
- end
10
-
11
- def skip?
12
- !FileTest.exist?('spec/support/record_results_formatter.rb')
13
- end
14
-
15
- TEST_RESULTS_FILE = '.spec-results'
16
- def run_check
17
- output = []
18
- unless relevant_tests.any?
19
- return :warn, 'No relevant tests for this change...write some?'
20
- end
21
-
22
- begin
23
- good_tests = File.open(TEST_RESULTS_FILE, 'r').readlines.map do |spec_file|
24
- File.expand_path spec_file.strip
25
- end
26
- rescue Errno::ENOENT
27
- good_tests = []
28
- end
29
-
30
- unless good_tests.any?
31
- return :bad,
32
- 'The relevant tests for this change have not yet been run using `specr`'
33
- end
34
-
35
- missed_tests = (relevant_tests - good_tests)
36
- unless missed_tests.empty?
37
- output << 'The following relevant tests have not been run recently:'
38
- output << missed_tests.sort
39
- return :bad, output
40
- end
41
-
42
- # Find files modified after the tests were run
43
- test_time = File.mtime(TEST_RESULTS_FILE)
44
- untested_files = modified_files.reject do |file|
45
- File.mtime(file) < test_time
46
- end
47
-
48
- unless untested_files.empty?
49
- output << 'The following files were modified after `specr` was run.'
50
- output << '(their associated tests may be broken):'
51
- output << untested_files.sort
52
- return :bad, output
53
- end
54
-
55
- return :good
56
- end
57
- end
58
- end
@@ -1,21 +0,0 @@
1
- module Overcommit::GitHook
2
- class Whitespace < HookSpecificCheck
3
- include HookRegistry
4
-
5
- def run_check
6
- paths = staged.collect(&:path).join(' ')
7
-
8
- # Catches hard tabs
9
- output = `grep -Inl "\t" #{paths}`
10
- unless output.empty?
11
- return :stop, "Don't use hard tabs:\n#{output}"
12
- end
13
-
14
- # Catches trailing whitespace, conflict markers etc
15
- output = `git diff --check --cached`
16
- return :stop, output unless $?.exitstatus.zero?
17
-
18
- :good
19
- end
20
- end
21
- end
@@ -1,22 +0,0 @@
1
- require 'yaml'
2
-
3
- module Overcommit::GitHook
4
- class YamlSyntax < HookSpecificCheck
5
- include HookRegistry
6
- file_type :yml
7
-
8
- def run_check
9
- clean = true
10
- output = []
11
- staged.each do |staged_file|
12
- begin
13
- YAML.load_file(staged_file.path)
14
- rescue ArgumentError => e
15
- output << "#{e.message} parsing #{staged_file.path}"
16
- clean = false
17
- end
18
- end
19
- return (clean ? :good : :bad), output
20
- end
21
- end
22
- end
@@ -1,90 +0,0 @@
1
- module Overcommit
2
- class Reporter
3
- def initialize(name, checks)
4
- @name = name
5
- @checks = checks
6
- @width = 60 - (@checks.map { |s| s.friendly_name.length }.max || 0)
7
- @results = []
8
- end
9
-
10
- def with_status(check, &block)
11
- title = " Checking #{check.name}"
12
- log.partial title unless check.stealth?
13
-
14
- status, output = yield
15
-
16
- print_incremental_result(title, status, output, check.stealth?)
17
- @results << status
18
- end
19
-
20
- def print_header
21
- log.log "Running #{@name} checks"
22
- end
23
-
24
- def print_result
25
- log.log # Newline
26
-
27
- case final_result
28
- when :good
29
- log.success "+++ All #{@name} checks passed"
30
- exit 0
31
- when :bad
32
- log.error "!!! One or more #{@name} checks failed"
33
- exit 1
34
- when :stop
35
- log.warning "*** One or more #{@name} checks needs attention"
36
- log.warning '*** If you really want to commit, use SKIP_CHECKS'
37
- log.warning "*** (takes a space-separated list of checks to skip, or 'all')"
38
- exit 1
39
- end
40
- end
41
-
42
- private
43
-
44
- def log
45
- Overcommit::Logger.instance
46
- end
47
-
48
- def print_incremental_result(title, status, output, stealth = false)
49
- if stealth
50
- return if status == :good
51
- log.partial title
52
- end
53
-
54
- print '.' * (@width - title.length)
55
- case status
56
- when :good
57
- log.success 'OK'
58
- when :bad
59
- log.error 'FAILED'
60
- print_report output
61
- when :warn
62
- log.warning 'WARNING'
63
- print_report output
64
- when :stop
65
- log.warning 'UH OH'
66
- print_report output
67
- else
68
- log.error '???'
69
- print_report "Check didn't return a status"
70
- exit 1
71
- end
72
- end
73
-
74
- def final_result
75
- return :bad if @results.include?(:bad)
76
- return :stop if @results.include?(:stop)
77
- return :good
78
- end
79
-
80
- OUTPUT_INDENT = ' ' * 4
81
- def print_report(output)
82
- unless output.empty?
83
- # Take each line of output and add indentation so it nests under check
84
- # name (except for the last newline if there is one)
85
- output = OUTPUT_INDENT + output.gsub(/\n(?!$)/, "\n#{OUTPUT_INDENT}")
86
- log.log output
87
- end
88
- end
89
- end
90
- end