pre-commit 0.11.0 → 0.12.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 (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