pre-commit 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -5
  3. data/bin/pre-commit +7 -5
  4. data/lib/plugins/pre_commit/checks/before_all.rb +13 -0
  5. data/lib/plugins/pre_commit/checks/ci.rb +12 -0
  6. data/lib/plugins/pre_commit/checks/closure.rb +19 -0
  7. data/lib/plugins/pre_commit/checks/coffeelint.rb +19 -0
  8. data/lib/plugins/pre_commit/checks/console_log.rb +13 -0
  9. data/lib/plugins/pre_commit/checks/debugger.rb +21 -0
  10. data/lib/plugins/pre_commit/checks/gemfile_path.rb +14 -0
  11. data/lib/plugins/pre_commit/checks/js.rb +36 -0
  12. data/lib/plugins/pre_commit/checks/jshint.rb +24 -0
  13. data/lib/plugins/pre_commit/checks/jslint.rb +24 -0
  14. data/lib/plugins/pre_commit/checks/local.rb +13 -0
  15. data/lib/plugins/pre_commit/checks/merge_conflict.rb +12 -0
  16. data/lib/plugins/pre_commit/checks/migration.rb +38 -0
  17. data/lib/plugins/pre_commit/checks/nb_space.rb +23 -0
  18. data/lib/plugins/pre_commit/checks/php.rb +27 -0
  19. data/lib/plugins/pre_commit/checks/pry.rb +12 -0
  20. data/lib/plugins/pre_commit/checks/rspec_focus.rb +13 -0
  21. data/lib/plugins/pre_commit/checks/rubocop.rb +46 -0
  22. data/lib/plugins/pre_commit/checks/ruby_symbol_hashrockets.rb +16 -0
  23. data/lib/plugins/pre_commit/checks/tabs.rb +14 -0
  24. data/lib/plugins/pre_commit/checks/whitespace.rb +21 -0
  25. data/lib/pre-commit/checks.rb +66 -58
  26. data/lib/pre-commit/cli.rb +29 -2
  27. data/lib/pre-commit/support/templates/automatic_hook +35 -0
  28. data/lib/pre-commit/support/templates/default_hook +35 -0
  29. data/lib/pre-commit/support/templates/manual_hook +14 -0
  30. metadata +101 -26
  31. data/lib/pre-commit/checks/ci_check.rb +0 -10
  32. data/lib/pre-commit/checks/closure_check.rb +0 -13
  33. data/lib/pre-commit/checks/console_log_check.rb +0 -11
  34. data/lib/pre-commit/checks/debugger_check.rb +0 -19
  35. data/lib/pre-commit/checks/gemfile_path_check.rb +0 -12
  36. data/lib/pre-commit/checks/js_check.rb +0 -35
  37. data/lib/pre-commit/checks/jshint_check.rb +0 -26
  38. data/lib/pre-commit/checks/jslint_check.rb +0 -22
  39. data/lib/pre-commit/checks/local_check.rb +0 -11
  40. data/lib/pre-commit/checks/merge_conflict_check.rb +0 -10
  41. data/lib/pre-commit/checks/migration_check.rb +0 -33
  42. data/lib/pre-commit/checks/nb_space_check.rb +0 -21
  43. data/lib/pre-commit/checks/php_check.rb +0 -25
  44. data/lib/pre-commit/checks/pry_check.rb +0 -10
  45. data/lib/pre-commit/checks/rspec_focus_check.rb +0 -11
  46. data/lib/pre-commit/checks/rubocop_check.rb +0 -38
  47. data/lib/pre-commit/checks/ruby_symbol_hashrockets.rb +0 -14
  48. data/lib/pre-commit/checks/tabs_check.rb +0 -12
  49. data/lib/pre-commit/checks/whitespace_check.rb +0 -16
  50. data/lib/pre-commit/support/templates/pre-commit-hook +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b62fa135fe8f60b7a5eafd7ef58ef2aa9eff6f7
4
- data.tar.gz: 0906b075207d03a6958dcbc576c3b4a5f6225990
3
+ metadata.gz: c7355c40a01a77e3e1a80b3aa54e0fad68f14384
4
+ data.tar.gz: 523aafecb538cb6ee6212a8aec9b3bb272475c53
5
5
  SHA512:
6
- metadata.gz: df2e83881c50460571ce4fc36bcff0f4e5127d94b6d3ad3e177d8369fdb642e8b990622a38bc2b0105e766921f765028785a9129f894f763006829b2714e5215
7
- data.tar.gz: 41b5486ceaf50650db83d3560ce6cab407d69449ddee3d175d6ea11af2d216d6e96a9eb58e3f86972bcecc7ee4b68e21bd9329f78bda65ffd15a5c09f8954352
6
+ metadata.gz: 442f543f6a1c50f4346bbb7ff94e0340c255ba81baff3f7a24ed9159f183173302ada1b5dfe92186c86fa587c2501c8318b6483dfbf94f65d032612ed9546f1c
7
+ data.tar.gz: 066024f84516424170d618568f1177d8ce34c3293131f348772af247143787033e0082341a9979aa6621470cb6b29b8aae88736e9068f60b0068efff0ec733ab
data/README.md CHANGED
@@ -1,7 +1,11 @@
1
1
  A better pre-commit hook for git.
2
2
 
3
- [![Current version](https://badge.fury.io/rb/pre-commit.png)][1] 
4
- [![Build status](https://secure.travis-ci.org/jish/pre-commit.png?branch=master)][2]
3
+ [![Current version](https://badge.fury.io/rb/pre-commit.png)](https://rubygems.org/gems/pre-commit)
4
+ [![Code Climate](https://codeclimate.com/github/jish/pre-commit.png)](https://codeclimate.com/github/jish/pre-commit)
5
+ [![Coverage Status](https://coveralls.io/repos/jish/pre-commit/badge.png?branch=master)](https://coveralls.io/r/jish/pre-commit?branch=master)
6
+ [![Build status](https://secure.travis-ci.org/jish/pre-commit.png?branch=master)](https://travis-ci.org/jish/pre-commit)
7
+ [![Dependency Status](https://gemnasium.com/jish/pre-commit.png)](https://gemnasium.com/jish/pre-commit)
8
+ [![Documentation](http://b.repl.ca/v1/yard-docs-blue.png)](http://rubydoc.info/gems/pre-commit/frames)
5
9
 
6
10
  ## Installation
7
11
 
@@ -36,6 +40,8 @@ These are the available checks:
36
40
  * migrations (Will make sure you check in the proper files after creating a Rails migration)
37
41
  * ci (Will run the `pre_commit:ci` rake task and pass or fail accordingly)
38
42
  * rubocop (Check ruby code style using the rubocop gem. Rubocop must be installed)
43
+ * before_all (Check your RSpec tests for the use of `before(:all)`)
44
+ * coffeelint (Check your coffeescript files using the [coffeelint gem.](https://github.com/clutchski/coffeelint))
39
45
 
40
46
  To configure which checks you would like to run, simply set the `pre-commit.checks` git configuration setting.
41
47
 
@@ -53,10 +59,13 @@ Note: If no checks are configured, a default set of checks is run:
53
59
 
54
60
  white_space, console_log, debugger, pry, tabs, jshint, migrations, merge_conflict, local
55
61
 
62
+ You may also enable checks that will produce warnings if detected but NOT stop the commit:
63
+
64
+ # From your git repo
65
+ $ git config "pre-commit.warnings" "jshint, ruby_symbol_hashrockets"
66
+
67
+
56
68
  For the rubocop check, you can tell it what config file to use by setting a path relative to the repo:
57
69
 
58
70
  # From your git repo
59
71
  $ git config "pre-commit.rubocop.config" "config/rubocop.yml"
60
-
61
- [1]: https://rubygems.org/gems/pre-commit
62
- [2]: https://travis-ci.org/jish/pre-commit
data/bin/pre-commit CHANGED
@@ -3,16 +3,18 @@
3
3
  require 'pre-commit/cli'
4
4
 
5
5
  if ARGV[0] != "install"
6
- puts "Usage: pre-commit install"
7
- exit(1)
6
+ abort "Usage: pre-commit install"
8
7
  end
9
8
 
10
9
  if !File.exists?(".git")
11
- puts "No .git directory found."
12
- exit(1)
10
+ abort "No .git directory found."
13
11
  end
14
12
 
15
- PreCommit::Cli.new.install
13
+ begin
14
+ PreCommit::Cli.new.install(ARGV[1])
15
+ rescue PreCommit::TemplateNotFound => e
16
+ abort e.message
17
+ end
16
18
 
17
19
  puts "Installed hook: #{PreCommit::Cli::PRE_COMMIT_HOOK_PATH}"
18
20
  puts
@@ -0,0 +1,13 @@
1
+ module PreCommit
2
+ module Checks
3
+ class BeforeAll
4
+ def self.call(staged_files)
5
+ staged_files.reject! { |f| File.extname(f) != ".rb" }
6
+ return if staged_files.empty?
7
+ errors = `#{PreCommit::Utils.grep} -e "before.*:all" #{staged_files.join(" ")} | grep -v \/\/`.strip
8
+ return unless $?.success?
9
+ "before(:all) found:\n#{errors}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module PreCommit
2
+ module Checks
3
+ class Ci
4
+ CI_TASK_NAME = 'pre_commit:ci'
5
+
6
+ def self.call(_)
7
+ return if system("rake #{CI_TASK_NAME} --silent")
8
+ "your test suite has failed, for the full output run `#{CI_TASK_NAME}`"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ module PreCommit
2
+ module Checks
3
+ class Closure
4
+ #TODO: add pluginator assets support
5
+ CLOSURE_PATH = File.expand_path("../../../../pre-commit/support/closure/compiler.jar", __FILE__)
6
+
7
+ def self.supports(name)
8
+ name == :closure_syntax_check
9
+ end
10
+ def self.call(staged_files)
11
+ return if staged_files.empty?
12
+ js_args = staged_files.map {|arg| "--js #{arg}"}.join(' ')
13
+ errors = `java -jar #{CLOSURE_PATH} #{js_args} --js_output_file /tmp/jammit.js 2>&1`.strip
14
+ return if errors.empty?
15
+ errors
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'pre-commit/utils'
2
+ require 'stringio'
3
+ require 'open3'
4
+
5
+ module PreCommit
6
+ module Checks
7
+ class Coffeelint
8
+ def self.call(staged_files)
9
+ staged_files = staged_files.grep(/\.coffee$/)
10
+ return if staged_files.empty?
11
+
12
+ args = staged_files.join(' ')
13
+
14
+ stdout, stderr, result = Open3.capture3("coffeelint #{args}")
15
+ stdout + stderr unless result.success?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module PreCommit
2
+ module Checks
3
+ class ConsoleLog
4
+ def self.call(staged_files)
5
+ staged_files.reject! { |f| File.extname(f) != ".js" }
6
+ return if staged_files.empty?
7
+ errors = `#{PreCommit::Utils.grep} -e "console\\.log" #{staged_files.join(" ")} | grep -v \/\/`.strip
8
+ return unless $?.success?
9
+ "console.log found:\n#{errors}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ require 'pre-commit/utils'
2
+
3
+ module PreCommit
4
+ module Checks
5
+ class Debugger
6
+ def self.call(staged_files)
7
+ files = files_to_check(staged_files)
8
+ return if files.empty?
9
+
10
+ errors = `#{PreCommit::Utils.grep} debugger #{files.join(" ")}`.strip
11
+ return unless $?.success?
12
+
13
+ "debugger statement(s) found:\n#{errors}"
14
+ end
15
+
16
+ def self.files_to_check(files)
17
+ files.reject { |file| File.basename(file) =~ /^Gemfile/ }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ require 'pre-commit/utils'
2
+
3
+ module PreCommit
4
+ module Checks
5
+ class GemfilePath
6
+ def self.call(staged_files)
7
+ return unless staged_files.include?("Gemfile")
8
+ errors = `#{PreCommit::Utils.grep} 'path:|:path\\s*=>' Gemfile`.strip
9
+ return unless $?.success?
10
+ "local path found in Gemfile:\n#{errors}"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ require 'pre-commit/utils'
2
+
3
+ module PreCommit
4
+ module Checks
5
+ class Js
6
+ def self.call(staged_files)
7
+ require 'execjs'
8
+ rescue RuntimeError, LoadError => e
9
+ $stderr.puts "Could not load execjs: #{e}"
10
+ else
11
+ staged_files = staged_files.select { |f| File.extname(f) == ".js" }
12
+ return if staged_files.empty?
13
+
14
+ errors = []
15
+ staged_files.each do |file|
16
+ error_list = Array(run_check(file))
17
+ error_list.each { |error_object| errors << display_error(error_object, file) }
18
+ end
19
+
20
+ return if errors.empty?
21
+ errors.join("\n")
22
+ end
23
+
24
+ def self.linter_src
25
+ raise "Must be defined by subclass"
26
+ end
27
+
28
+ def self.display_error(error_object, file)
29
+ return "" unless error_object
30
+
31
+ line = error_object['line'].to_i + 1
32
+ "#{error_object['reason']}\n#{file}:#{line} #{error_object['evidence']}"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,24 @@
1
+ require 'plugins/pre_commit/checks/js'
2
+
3
+ module PreCommit
4
+ module Checks
5
+ class Jshint < Js
6
+ def self.config
7
+ if config_file = [ENV['JSHINT_CONFIG'], ".jshintrc"].compact.detect { |f| File.exist?(f) }
8
+ ExecJS.exec("return (#{File.read(config_file)});")
9
+ else
10
+ {}
11
+ end
12
+ end
13
+
14
+ def self.run_check(file)
15
+ context = ExecJS.compile(File.read(linter_src))
16
+ context.call("JSHINT", File.read(file), config, config["globals"])
17
+ end
18
+
19
+ def self.linter_src
20
+ File.expand_path("../../../../pre-commit/support/jshint/jshint.js", __FILE__)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'plugins/pre_commit/checks/js'
2
+
3
+ module PreCommit
4
+ module Checks
5
+ class Jslint < Js
6
+ def self.supports(name)
7
+ [ :js_lint, :js_lint_all, :js_lint_new ].include?(name)
8
+ end
9
+
10
+ def self.run_check(file)
11
+ context = ExecJS.compile(File.read(linter_src))
12
+ if !(context.call('JSLINT', File.read(file)))
13
+ context.exec('return JSLINT.errors;')
14
+ else
15
+ []
16
+ end
17
+ end
18
+
19
+ def self.linter_src
20
+ File.expand_path("../../../../pre-commit/support/jslint/lint.js", __FILE__)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module PreCommit
2
+ module Checks
3
+ class Local
4
+ DEFAULT_LOCATION = "config/pre-commit.rb"
5
+
6
+ def self.call(staged_files, script=DEFAULT_LOCATION)
7
+ return unless File.exist?(script)
8
+ output = `ruby #{script} #{staged_files.join(" ")} 2>&1`
9
+ "#{script} failed:\n#{output}" unless $?.success?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module PreCommit
2
+ module Checks
3
+ class MergeConflict
4
+ def self.call(staged_files)
5
+ return if staged_files.empty?
6
+ errors = `#{PreCommit::Utils.grep} '<<<<<<<' #{staged_files.join(" ")}`.strip
7
+ return unless $?.success?
8
+ "detected a merge conflict\n#{errors}"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,38 @@
1
+ module PreCommit
2
+ module Checks
3
+ class Migration
4
+ def self.supports(name)
5
+ name == :migrations
6
+ end
7
+ class << self
8
+ def call(staged_files)
9
+ migration_files = migration_files(staged_files)
10
+ schema_files = schema_files(staged_files)
11
+
12
+ if migration_files.any? && schema_files.none?
13
+ "It looks like you're adding a migration, but did not update the schema file"
14
+ elsif migration_files.none? && schema_files.any?
15
+ "You're trying to change the schema without adding a migration file"
16
+ elsif migration_files.any? && schema_files.any?
17
+ versions = migration_files.map { |f| f[/\d+/] }
18
+ schema = schema_files.map { |f| File.read(f) }.join
19
+ missing_versions = versions.select { |version| !schema.include?(version) }
20
+ if missing_versions.any?
21
+ "You did not add the schema versions for #{versions.join(', ')} to #{schema_files.join(' or ')}"
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def migration_files(staged_files)
29
+ staged_files.grep(/db\/migrate\/.*\.rb/)
30
+ end
31
+
32
+ def schema_files(staged_files)
33
+ staged_files.select { |f| File.basename(f) =~ /schema\.rb|structure.*\.sql/ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ module PreCommit
3
+ module Checks
4
+ class NbSpace
5
+ def self.call(staged_files)
6
+ nb_space = " "
7
+ raise "you messed that up" unless nb_space.bytes.to_a == [194, 160]
8
+
9
+ staged_files.reject! { |f| f =~ /^vendor\// || !File.read(f, encoding: 'utf-8').include?(nb_space) }
10
+
11
+ bad = staged_files.map do |file|
12
+ content = File.read(file).lines.to_a
13
+ line_no = content.index { |l| l.include?(nb_space) }
14
+ char_no = content[line_no].index(nb_space)
15
+ [file, line_no, char_no]
16
+ end
17
+
18
+ return if bad.empty?
19
+ "Detected non-breaking space in #{bad.map { |f,l,c| "#{f}:#{l+1} character:#{c+1}" }.join(" and")}, remove it!"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ require 'pre-commit/utils'
2
+
3
+ module PreCommit
4
+ module Checks
5
+ class Php
6
+ def self.call(staged_files)
7
+ staged_files = staged_files.grep /\.(php|engine|theme|install|inc|module|test)$/
8
+ return if staged_files.empty?
9
+
10
+ errors = staged_files.map { |file| run_check(file) }.compact
11
+ return if errors.empty?
12
+
13
+ errors.join("\n")
14
+ end
15
+
16
+ def self.run_check(file)
17
+ # We force PHP to display errors otherwise they will likely end up in the
18
+ # error_log and not in stdout.
19
+ result = `php -d display_errors=1 -l #{file} 2>&1`
20
+ # Filter out the obvious note from PHP.
21
+ result = result.split($/).find_all {|line| line !~ /Errors/}.join($/)
22
+ # If PHP exited non-zero then there was a parse error.
23
+ result.strip unless $? == 0
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ module PreCommit
2
+ module Checks
3
+ class Pry
4
+ def self.call(staged_files)
5
+ return if staged_files.empty?
6
+ result = `#{PreCommit::Utils.grep} binding.pry #{staged_files.join(" ")}`.strip
7
+ return unless $?.success?
8
+ "binding.pry found:\n#{result}"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module PreCommit
2
+ module Checks
3
+ class RspecFocus
4
+ def self.call(staged_files)
5
+ staged_files = staged_files.grep(/_spec\.rb$/)
6
+ return if staged_files.empty?
7
+ result = `#{PreCommit::Utils.grep} ':focus' #{staged_files.join(" ")}`.strip
8
+ return unless $?.success?
9
+ ":focus found in specs:\n#{result}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,46 @@
1
+ require 'pre-commit/utils'
2
+ require 'stringio'
3
+
4
+ module PreCommit
5
+ module Checks
6
+ class Rubocop
7
+ def self.supports(name)
8
+ [ :rubocop_all, :rubocop_new ].include?(name)
9
+ end
10
+ def self.call(staged_files)
11
+ require 'rubocop'
12
+ rescue LoadError => e
13
+ $stderr.puts "Could not find rubocop: #{e}"
14
+ else
15
+ staged_files = staged_files.grep(/\.rb$/)
16
+ return if staged_files.empty?
17
+ config_file = `git config pre-commit.rubocop.config`.chomp
18
+
19
+ args = staged_files
20
+ if !config_file.empty?
21
+ if !File.exist? config_file
22
+ $stderr.puts "Warning: rubocop config file '" + config_file + "' does not exist"
23
+ $stderr.puts "Set the path to the config file using:"
24
+ $stderr.puts "\tgit config pre-commit.rubocop.config 'path/relative/to/git/dir/rubocop.yml'"
25
+ $stderr.puts "rubocop will use its default configuration or look for a .rubocop.yml file\n\n"
26
+ else
27
+ args = ['-c', config_file] + args
28
+ end
29
+ end
30
+
31
+ success, captured = capture { Rubocop::CLI.new.run(args) == 0 }
32
+ captured unless success
33
+ end
34
+
35
+ def self.capture
36
+ $stdout, stdout = StringIO.new, $stdout
37
+ $stderr, stderr = StringIO.new, $stderr
38
+ result = yield
39
+ [result, $stdout.string + $stderr.string]
40
+ ensure
41
+ $stdout = stdout
42
+ $stderr = stderr
43
+ end
44
+ end
45
+ end
46
+ end