overcommit 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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