pre-commit 0.19.0 → 0.20.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 47b088bf66a3dce520c9a2e2c7b2573a5da3dc4d
4
- data.tar.gz: b2712aafb68d68ae5226e1a79800e705b8ec1947
3
+ metadata.gz: 0b7eca26aaae49efaf8967fb7a02d01521f272cc
4
+ data.tar.gz: 7e36f001ca2d85847d5038b757f442ffbb411a4e
5
5
  SHA512:
6
- metadata.gz: ed5b63347c42c6cd96782865d9513f2f63a3bb7ec5e924c27ef403667981b3e5d51ef6d557e719a7542ef0e36073de715aeeee83ea172105565e9df2755280ed
7
- data.tar.gz: c90634c849ddc7fd8e294fa408b3474c0c23e7f85a35bb6492e14311c289dac127ecca75b1b07bcc8ecfece8feefc61bf16d250be52298de32fd6ad53fe9b749
6
+ metadata.gz: f21965abc93d4cec2c941d53b519aa8bcf0416334a329784e061d8791108651f289184d7e0504e54da1b57e5b93d5395992753f856fbde69f08735c7810940e9
7
+ data.tar.gz: df10779b7b8a0be223b55b6f70a0cd476b080bc75074b39832a3b4409da5c966aefcd55f28ff5b95e8010142525e3e6fe611ca736247f0409b966e68f3dc2e54
data/README.md CHANGED
@@ -107,4 +107,14 @@ pre-commit run <file-list> # run on the list of files, patterns not supported
107
107
  - `yaml` - reads configuration from `/etc/pre_commit.yml`, `$HOME/.pre_commit.yml` and `config/pre_commit.yml`, allows `config/pre_commit.yml` updates
108
108
  - `env` - reads configuration from environment variables
109
109
 
110
+ ## Excluding files from checks
111
+
112
+ `pre-commit` uses `git` to get list of files to check, you can ignore
113
+ the list of git files to check with:
114
+
115
+ 1. `.gitignore` - git supported file shared beteen all checkouts
116
+ 2. `.git/info/exclude` - git supported file only for this checkout
117
+ 3. `.pre_commit.ignore` - `pre-commit` specific list can be shared,
118
+ [Allowed filters](http://www.ruby-doc.org/core-2.1.3/File.html#method-c-fnmatch)
119
+
110
120
  ## [Contributing](CONTRIBUTING.md)
@@ -9,15 +9,15 @@ module PreCommit
9
9
  end
10
10
 
11
11
  def extra_grep
12
- " | grep -v \/\/"
12
+ %w{-v //}
13
13
  end
14
14
 
15
15
  def message
16
- "before(:all) found:\n"
16
+ "before(:all) found:"
17
17
  end
18
18
 
19
19
  def pattern
20
- '-e "before.*:all"'
20
+ "before.*:all"
21
21
  end
22
22
 
23
23
  def self.description
@@ -7,7 +7,9 @@ module PreCommit
7
7
 
8
8
  def call(_)
9
9
  return if system("rake #{Ci::CI_TASK_NAME} --silent")
10
- "your test suite has failed, for the full output run `#{CI_TASK_NAME}`"
10
+ PreCommit::ErrorList.new(
11
+ "your test suite has failed, for the full output run `#{CI_TASK_NAME}`"
12
+ )
11
13
  end
12
14
 
13
15
  def self.description
@@ -8,9 +8,13 @@ module PreCommit
8
8
  staged_files = staged_files.grep(/\.coffee$/)
9
9
  return if staged_files.empty?
10
10
 
11
- args = (config_file_flag + staged_files).join(' ')
11
+ result =
12
+ in_groups(staged_files).map do |files|
13
+ args = %w{coffeelint} + config_file_flag + files
14
+ execute(args)
15
+ end.compact
12
16
 
13
- execute("coffeelint #{args}")
17
+ result.empty? ? nil : result.join("\n")
14
18
  end
15
19
 
16
20
  def config_file_flag
@@ -9,15 +9,15 @@ module PreCommit
9
9
  end
10
10
 
11
11
  def extra_grep
12
- " | grep -v \/\/"
12
+ %w{-v //}
13
13
  end
14
14
 
15
15
  def message
16
- "console.log found:\n"
16
+ "console.log found:"
17
17
  end
18
18
 
19
19
  def pattern
20
- '-e "console\\.log"'
20
+ "console\\.log"
21
21
  end
22
22
 
23
23
  def self.description
@@ -9,11 +9,11 @@ module PreCommit
9
9
  end
10
10
 
11
11
  def message
12
- "debugger statement(s) found:\n"
12
+ "debugger statement(s) found:"
13
13
  end
14
14
 
15
15
  def pattern
16
- '-e "^[ ]*debugger"'
16
+ "^[ ]*debugger"
17
17
  end
18
18
 
19
19
  def self.description
@@ -9,15 +9,15 @@ module PreCommit
9
9
  end
10
10
 
11
11
  def message
12
- "local path found in Gemfile:\n"
12
+ "local path found in Gemfile:"
13
13
  end
14
14
 
15
15
  def pattern
16
- "'path:|:path\\s*=>'"
16
+ "path:|:path\\s*=>"
17
17
  end
18
18
 
19
19
  def extra_grep
20
- " | grep -v '#'"
20
+ %w{-v #}
21
21
  end
22
22
 
23
23
  def self.description
@@ -4,17 +4,8 @@ module PreCommit
4
4
  module Checks
5
5
  class Jshint < Js
6
6
 
7
- def js_config
8
- if config_file
9
- ExecJS.exec("return (#{File.read(config_file)});")
10
- else
11
- {}
12
- end
13
- end
14
-
15
7
  def run_check(file)
16
- context = ExecJS.compile(File.read(linter_src))
17
- context.call("JSHINT", File.read(file), js_config, js_config["globals"])
8
+ context.call("JSHINT._getErrors", File.read(file), js_config, js_config["globals"])
18
9
  end
19
10
 
20
11
  def linter_src
@@ -29,6 +20,25 @@ module PreCommit
29
20
  "Checks javascript files with JSHint."
30
21
  end
31
22
 
23
+ private
24
+
25
+ def context
26
+ @context ||= ExecJS.compile(File.read(linter_src) << <<-JAVASCRIPT)
27
+ ;JSHINT._getErrors = function(source, options, globals) {
28
+ JSHINT(source, options, globals);
29
+ return JSHINT.errors;
30
+ }
31
+ JAVASCRIPT
32
+ end
33
+
34
+ def js_config
35
+ @js_config ||= if config_file
36
+ ExecJS.exec("return (#{File.read(config_file)});")
37
+ else
38
+ {}
39
+ end
40
+ end
41
+
32
42
  end
33
43
  end
34
44
  end
@@ -4,16 +4,22 @@ module PreCommit
4
4
  module Checks
5
5
  class Local < Plugin
6
6
 
7
- DEFAULT_LOCATION = "config/pre-commit.rb"
7
+ attr_writer :script
8
8
 
9
- def call(staged_files, script=Local::DEFAULT_LOCATION)
10
- return unless File.exist?(script)
9
+ def call(staged_files)
10
+ return unless script
11
11
  output = `ruby #{script} #{staged_files.join(" ")} 2>&1`
12
12
  "#{script} failed:\n#{output}" unless $?.success?
13
13
  end
14
14
 
15
15
  def self.description
16
- "Executes 'ruby #{DEFAULT_LOCATION}'."
16
+ "Executes a custom script located at config/pre_commit.rb"
17
+ end
18
+
19
+ def script
20
+ @script ||= ["config/pre_commit.rb", "config/pre-commit.rb"].detect do |file|
21
+ File.exist?(file)
22
+ end
17
23
  end
18
24
 
19
25
  end
@@ -5,11 +5,11 @@ module PreCommit
5
5
  class MergeConflict < Grep
6
6
 
7
7
  def message
8
- "detected a merge conflict\n"
8
+ "detected a merge conflict"
9
9
  end
10
10
 
11
11
  def pattern
12
- "'<<<<<<<'"
12
+ "<<<<<<<"
13
13
  end
14
14
 
15
15
  def self.description
@@ -5,7 +5,7 @@ module PreCommit
5
5
  class Pry < Grep
6
6
 
7
7
  def message
8
- "binding.pry found:\n"
8
+ "binding.pry found:"
9
9
  end
10
10
 
11
11
  def pattern
@@ -9,11 +9,11 @@ module PreCommit
9
9
  end
10
10
 
11
11
  def message
12
- ":focus found in specs:\n"
12
+ ":focus found in specs:"
13
13
  end
14
14
 
15
15
  def pattern
16
- "'(describe|context|it).*(:focus|focus:).*do'"
16
+ "(describe|context|it).*(:focus|focus:).*do"
17
17
  end
18
18
 
19
19
  def self.description
@@ -21,7 +21,7 @@ module PreCommit
21
21
  staged_files = staged_files.grep(/\.rb$/)
22
22
  return if staged_files.empty?
23
23
 
24
- args = config_file_flag + ["--force-exclusion"] + staged_files
24
+ args = config_file_flag + user_supplied_flags + ["--force-exclusion"] + staged_files
25
25
 
26
26
  success, captured = capture { ::RuboCop::CLI.new.run(args) == 0 }
27
27
  captured unless success
@@ -41,6 +41,10 @@ module PreCommit
41
41
  config_file ? ['-c', config_file] : []
42
42
  end
43
43
 
44
+ def user_supplied_flags
45
+ Array(config.get('rubocop.flags')).reject(&:empty?)
46
+ end
47
+
44
48
  def alternate_config_file
45
49
  '.rubocop.yml'
46
50
  end
@@ -9,11 +9,11 @@ module PreCommit
9
9
  end
10
10
 
11
11
  def message
12
- "detected :symbol => value hashrocket:\n"
12
+ "detected :symbol => value hashrocket:"
13
13
  end
14
14
 
15
15
  def pattern
16
- '\'[^:](:{1}(?:\$|@|@@|[_A-Za-z])?\w*[=!?]?\s*=>\s*)\''
16
+ '[^:](:{1}(?:\$|@|@@|[_A-Za-z])?\w*[=!?]?\s*=>\s*)'
17
17
  end
18
18
 
19
19
  def self.description
@@ -8,9 +8,13 @@ module PreCommit
8
8
  staged_files = staged_files.grep(/\.scss$/)
9
9
  return if staged_files.empty?
10
10
 
11
- args = (config_file_flag + staged_files).join(' ')
11
+ result =
12
+ in_groups(staged_files).map do |files|
13
+ args = %w{scss-lint} + config_file_flag + files
14
+ execute(args)
15
+ end.compact
12
16
 
13
- execute("scss-lint #{args}")
17
+ result.empty? ? nil : result.join("\n")
14
18
  end
15
19
 
16
20
  def config_file_flag
@@ -5,11 +5,11 @@ module PreCommit
5
5
  class Tabs < Grep
6
6
 
7
7
  def message
8
- "detected tab before initial space:\n"
8
+ "detected tab before initial space:"
9
9
  end
10
10
 
11
11
  def pattern
12
- "'^ *\t'"
12
+ "^ *\t"
13
13
  end
14
14
 
15
15
  def self.description
@@ -1,10 +1,13 @@
1
1
  require 'yaml'
2
+ require "pre-commit/configuration/top_level"
2
3
 
3
4
  module PreCommit
4
5
  class Configuration
5
6
  class Providers
6
7
 
7
8
  class Yaml
9
+ include PreCommit::Configuration::TopLevel
10
+
8
11
  def self.priority
9
12
  20
10
13
  end
@@ -55,11 +58,6 @@ module PreCommit
55
58
  File.join(top_level, 'config', 'pre_commit.yml')
56
59
  end
57
60
 
58
- def top_level
59
- top_level = `git rev-parse --show-toplevel`.chomp.strip
60
- raise "no git repo!" if top_level == ""
61
- top_level
62
- end
63
61
  end
64
62
 
65
63
  end
@@ -1,9 +1,10 @@
1
- require 'pre-commit/checks/plugin'
2
- require 'shellwords'
1
+ require 'pre-commit/checks/shell'
2
+ require 'pre-commit/error_list'
3
+ require 'pre-commit/line'
3
4
 
4
5
  module PreCommit
5
6
  module Checks
6
- class Grep < Plugin
7
+ class Grep < Shell
7
8
  class PaternNotSet < StandardError
8
9
  def message
9
10
  "Please define 'pattern' method."
@@ -17,7 +18,7 @@ module PreCommit
17
18
  end
18
19
 
19
20
  def extra_grep
20
- @extra_grep or ""
21
+ @extra_grep or []
21
22
  end
22
23
 
23
24
  def message
@@ -31,21 +32,43 @@ module PreCommit
31
32
  # general code:
32
33
 
33
34
  def call(staged_files)
34
- staged_files = files_filter(staged_files).map(&:shellescape)
35
+ staged_files = files_filter(staged_files)
35
36
  return if staged_files.empty?
36
- errors = `#{grep} #{pattern} #{staged_files.join(" ")}#{extra_grep}`
37
- return unless $?.success?
38
- "#{message}#{errors}"
37
+
38
+ result =
39
+ in_groups(staged_files).map do |files|
40
+ args = grep + [pattern] + files
41
+ args += ["|", "grep"] + extra_grep if !extra_grep.nil? and !extra_grep.empty?
42
+ execute(args, success_status: false)
43
+ end.compact
44
+
45
+ result.empty? ? nil : parse_errors(message, result)
39
46
  end
40
47
 
41
48
  private
42
49
 
50
+ def parse_errors(message, list)
51
+ result = PreCommit::ErrorList.new(message)
52
+ result.errors +=
53
+ list.map do |group|
54
+ group.split(/\n/)
55
+ end.flatten.compact.map do |line|
56
+ PreCommit::Line.new(nil, *parse_error(line))
57
+ end
58
+ result
59
+ end
60
+
61
+ def parse_error(line)
62
+ matches = /^([^:]+):([[:digit:]]+):(.*)$/.match(line)
63
+ matches and matches.captures
64
+ end
65
+
43
66
  def grep(grep_version = nil)
44
67
  grep_version ||= detect_grep_version
45
68
  if grep_version =~ /FreeBSD/
46
- "grep -EnIH"
69
+ %w{grep -EnIH}
47
70
  else
48
- "grep -PnIH"
71
+ %w{grep -PnIH}
49
72
  end
50
73
  end
51
74
 
@@ -1,5 +1,6 @@
1
1
  require 'plugins/pluginator/extensions/conversions'
2
2
  require 'pre-commit/checks/plugin/config_file'
3
+ require 'pre-commit/line'
3
4
 
4
5
  module PreCommit
5
6
  module Checks
@@ -28,6 +29,17 @@ module PreCommit
28
29
  def alternate_config_file
29
30
  ''
30
31
  end
32
+
33
+ # group files in packs smaller then 127kB (1000 files)
34
+ # 127k based on http://www.in-ulm.de/~mascheck/various/argmax/
35
+ # and 262144 limit on OSX - my env size /2 to be safe
36
+ # assuming mean file length shorter then 127 chars splitting to
37
+ # groups of 1000 files, each_slice for simplicity, doing real
38
+ # check could be to time consuming
39
+ def in_groups(files, group_size = 1000)
40
+ files.each_slice(group_size)
41
+ end
42
+
31
43
  end
32
44
  end
33
45
  end
@@ -1,5 +1,5 @@
1
1
  require 'pre-commit/checks/plugin'
2
- require 'open3'
2
+ require 'shellwords'
3
3
 
4
4
  module PreCommit
5
5
  module Checks
@@ -7,9 +7,22 @@ module PreCommit
7
7
 
8
8
  private
9
9
 
10
- def execute(command)
11
- _, stdout, stderr, process = Open3.popen3(command)
12
- stdout.read + stderr.read unless process.value.success?
10
+ def execute(*args)
11
+ options = args.last.is_a?(::Hash) ? args.pop : {}
12
+ args = build_command(*args)
13
+ execute_raw(args, options)
14
+ end
15
+
16
+ def build_command(*args)
17
+ args.flatten.map do |arg|
18
+ arg = arg.shellescape if arg != '|' && arg != '&&' && arg != '||'
19
+ arg
20
+ end.join(" ")
21
+ end
22
+
23
+ def execute_raw(command, options = {})
24
+ result = `#{command} 2>&1`
25
+ $?.success? == (options.fetch(:success_status, true)) ? nil : result
13
26
  end
14
27
  end
15
28
  end