pre-commit 0.12.0 → 0.13.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +39 -16
  3. data/bin/pre-commit +1 -12
  4. data/lib/plugins/pluginator/extensions/find_check.rb +26 -0
  5. data/lib/plugins/pre_commit/checks/before_all.rb +23 -7
  6. data/lib/plugins/pre_commit/checks/ci.rb +10 -3
  7. data/lib/plugins/pre_commit/checks/closure.rb +12 -4
  8. data/lib/plugins/pre_commit/checks/coffeelint.rb +9 -4
  9. data/lib/plugins/pre_commit/checks/common.rb +17 -0
  10. data/lib/plugins/pre_commit/checks/console_log.rb +23 -7
  11. data/lib/plugins/pre_commit/checks/csslint.rb +32 -0
  12. data/lib/plugins/pre_commit/checks/debugger.rb +14 -10
  13. data/lib/plugins/pre_commit/checks/gemfile_path.rb +18 -7
  14. data/lib/plugins/pre_commit/checks/jshint.rb +10 -4
  15. data/lib/plugins/pre_commit/checks/jslint.rb +11 -5
  16. data/lib/plugins/pre_commit/checks/local.rb +10 -2
  17. data/lib/plugins/pre_commit/checks/merge_conflict.rb +15 -6
  18. data/lib/plugins/pre_commit/checks/migration.rb +32 -26
  19. data/lib/plugins/pre_commit/checks/nb_space.rb +10 -2
  20. data/lib/plugins/pre_commit/checks/php.rb +10 -4
  21. data/lib/plugins/pre_commit/checks/pry.rb +15 -6
  22. data/lib/plugins/pre_commit/checks/rails.rb +17 -0
  23. data/lib/plugins/pre_commit/checks/rspec_focus.rb +19 -7
  24. data/lib/plugins/pre_commit/checks/rubocop.rb +20 -8
  25. data/lib/plugins/pre_commit/checks/ruby.rb +17 -0
  26. data/lib/plugins/pre_commit/checks/ruby_symbol_hashrockets.rb +17 -8
  27. data/lib/plugins/pre_commit/checks/tabs.rb +15 -8
  28. data/lib/plugins/pre_commit/checks/whitespace.rb +28 -5
  29. data/lib/plugins/pre_commit/configuration/providers/README.md +10 -0
  30. data/lib/plugins/pre_commit/configuration/providers/default.rb +34 -0
  31. data/lib/plugins/pre_commit/configuration/providers/git.rb +26 -0
  32. data/lib/plugins/pre_commit/configuration/providers/git_old.rb +28 -0
  33. data/lib/plugins/pre_commit/configuration/providers/yaml.rb +67 -0
  34. data/lib/pre-commit.rb +28 -1
  35. data/lib/pre-commit/checks.rb +1 -98
  36. data/lib/pre-commit/checks/grep.rb +57 -0
  37. data/lib/{plugins/pre_commit → pre-commit}/checks/js.rb +15 -7
  38. data/lib/pre-commit/checks/plugin.rb +13 -0
  39. data/lib/pre-commit/cli.rb +46 -19
  40. data/lib/pre-commit/configuration.rb +54 -0
  41. data/lib/pre-commit/configuration/providers.rb +53 -0
  42. data/lib/pre-commit/installer.rb +54 -0
  43. data/lib/pre-commit/list_evaluator.rb +85 -0
  44. data/lib/pre-commit/plugins_list.rb +87 -0
  45. data/lib/pre-commit/runner.rb +54 -9
  46. data/lib/pre-commit/support/csslint/csslint.js +9259 -0
  47. data/lib/pre-commit/utils/git_conversions.rb +56 -0
  48. data/lib/pre-commit/utils/staged_files.rb +21 -0
  49. metadata +47 -30
  50. data/lib/pre-commit/support/templates/automatic_hook +0 -35
  51. data/lib/pre-commit/support/templates/default_hook +0 -35
  52. data/lib/pre-commit/support/templates/manual_hook +0 -14
  53. data/lib/pre-commit/utils.rb +0 -27
@@ -0,0 +1,13 @@
1
+ module PreCommit
2
+ module Checks
3
+ class Plugin
4
+ attr_accessor :pluginator, :config
5
+
6
+ def initialize(pluginator, config, list)
7
+ @pluginator = pluginator
8
+ @config = config
9
+ @list = list
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,4 +1,7 @@
1
1
  require 'fileutils'
2
+ require 'pre-commit/configuration'
3
+ require 'pre-commit/installer'
4
+ require 'pre-commit/list_evaluator'
2
5
 
3
6
  module PreCommit
4
7
 
@@ -6,36 +9,60 @@ module PreCommit
6
9
 
7
10
  class Cli
8
11
 
9
- PRE_COMMIT_HOOK_PATH = '.git/hooks/pre-commit'
10
- TEMPLATE_DIR = File.expand_path("../support/templates/", __FILE__)
12
+ def initialize(*args)
13
+ @args = args
14
+ end
11
15
 
12
- attr_reader :templates
16
+ def execute()
17
+ action_name = @args.shift or 'help'
18
+ action = "execute_#{action_name}".to_sym
19
+ if respond_to?(action)
20
+ then send(action, *@args)
21
+ else execute_help(action_name, *@args)
22
+ end
23
+ end
13
24
 
14
- def initialize
15
- @templates = load_templates
25
+ def execute_help(*args)
26
+ warn "Unknown parameters: #{args * " "}" unless args.empty?
27
+ warn "Usage: pre-commit install"
28
+ warn "Usage: pre-commit list"
29
+ warn "Usage: pre-commit plugins"
30
+ warn "Usage: pre-commit <enable|disbale> <git|yaml> <checks|warnings> check1 [check2...]"
31
+ args.empty? # return status, it's ok if user requested help
16
32
  end
17
33
 
18
- def install(key = nil)
19
- key ||= "default"
20
- hook = templates[key.sub(/^--/, "")]
34
+ def execute_install(key = nil, *args)
35
+ PreCommit::Installer.new(key).install
36
+ end
21
37
 
22
- raise TemplateNotFound.new("Could not find template #{key}") unless hook
38
+ def execute_list(*args)
39
+ puts list_evaluator.list
40
+ true
41
+ end
23
42
 
24
- FileUtils.cp(hook, PRE_COMMIT_HOOK_PATH)
25
- FileUtils.chmod(0755, PRE_COMMIT_HOOK_PATH)
43
+ def execute_plugins(*args)
44
+ puts list_evaluator.plugins
45
+ true
26
46
  end
27
47
 
28
- private
48
+ def execute_enable(*args)
49
+ config.enable(*args)
50
+ rescue ArgumentError
51
+ execute_help('enable', *args)
52
+ end
29
53
 
30
- def load_templates
31
- pattern = File.join(TEMPLATE_DIR, "*_hook")
54
+ def execute_disable(*args)
55
+ config.disable(*args)
56
+ rescue ArgumentError
57
+ execute_help('disable', *args)
58
+ end
32
59
 
33
- Dir.glob(pattern).inject({}) do |hash, file|
34
- key = file.match(/\/([^\/]+?)_hook$/)[1]
35
- hash[key] = file
60
+ def config
61
+ @config ||= PreCommit::Configuration.new(PreCommit.pluginator)
62
+ end
36
63
 
37
- hash
38
- end
64
+ def list_evaluator
65
+ @list_evaluator ||= PreCommit::ListEvaluator.new(config)
39
66
  end
40
67
 
41
68
  end
@@ -0,0 +1,54 @@
1
+ require 'pluginator'
2
+ require 'pre-commit/configuration/providers'
3
+ require 'pre-commit/plugins_list'
4
+
5
+ module PreCommit
6
+ class Configuration
7
+ attr_reader :pluginator, :providers
8
+
9
+ def initialize(pluginator, providers = nil)
10
+ @pluginator = (pluginator or PreCommit.pluginator)
11
+ @providers = (providers or Providers.new(@pluginator))
12
+ end
13
+
14
+ def get(name)
15
+ @providers[name.to_sym]
16
+ end
17
+
18
+ def get_arr(name)
19
+ value = get(name)
20
+ case value
21
+ when nil then []
22
+ when Array then value
23
+ else raise PreCommit::NotAnArray.new
24
+ end
25
+ end
26
+
27
+ def get_combined(name)
28
+ get_arr(name) + get_arr("#{name}_add")
29
+ end
30
+
31
+ def enable(plugin_name, type, check1, *checks)
32
+ checks.unshift(check1) # check1 is ArgumentError triger
33
+ checks.map!(&:to_sym)
34
+ @providers.update( plugin_name, "#{type}_remove", :-, checks )
35
+ @providers.update( plugin_name, "#{type}_add", :+, (checks or []) - (@providers.default(type) or []) )
36
+ true
37
+ rescue PreCommit::PluginNotFound => e
38
+ $stderr.puts e
39
+ false
40
+ end
41
+
42
+ def disable(plugin_name, type, check1, *checks)
43
+ checks.unshift(check1) # check1 is ArgumentError triger
44
+ checks.map!(&:to_sym)
45
+ @providers.update( plugin_name, "#{type}_add", :-, checks )
46
+ @providers.update( plugin_name, "#{type}_remove", :+, checks )
47
+ true
48
+ rescue PreCommit::PluginNotFound => e
49
+ warn e
50
+ false
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,53 @@
1
+ require 'plugins/pluginator/extensions/conversions'
2
+
3
+ module PreCommit
4
+ class NotAnArray < StandardError
5
+ end
6
+
7
+ class PluginNotFound < StandardError
8
+ end
9
+
10
+ class Configuration
11
+ class Providers
12
+ include Pluginator::Extensions::Conversions
13
+
14
+ def initialize(pluginator, plugins = nil)
15
+ @pluginator = pluginator
16
+ @plugins = plugins
17
+ end
18
+
19
+ def [](name)
20
+ plugins.map{|plugin| plugin[name] }.compact.last
21
+ end
22
+
23
+ def default(name)
24
+ plugins[0][name]
25
+ end
26
+
27
+ def update(plugin_name, name, operation, list)
28
+ plugin = find_update_plugin(plugin_name)
29
+ name = name.to_sym
30
+ value = plugin[name] || []
31
+ raise PreCommit::NotAnArray.new unless Array === value
32
+ value = value.send(operation, list)
33
+ plugin.update(name, value)
34
+ end
35
+
36
+ def list
37
+ plugins.map{|plugin| "#{class2string(class2name(plugin.class))}(#{plugin.class.priority})" }
38
+ end
39
+
40
+ private
41
+ def plugins
42
+ @plugins ||= @pluginator['configuration/providers'].sort_by(&:priority).map(&:new)
43
+ end
44
+
45
+ def find_update_plugin(plugin_name)
46
+ plugin = plugins.detect{|plugin| class2string(class2name(plugin.class)) == plugin_name.to_s}
47
+ raise PluginNotFound.new("Plugin not found for #{plugin_name}.") unless plugin
48
+ plugin
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,54 @@
1
+ require 'fileutils'
2
+ require 'pre-commit/configuration'
3
+
4
+ module PreCommit
5
+
6
+ class Installer
7
+
8
+ TARGET_HOOK_PATH = '.git/hooks/pre-commit'
9
+ TEMPLATE_DIR = File.expand_path("../../../templates/hooks/", __FILE__)
10
+
11
+ attr_reader :key
12
+
13
+ def initialize(key = nil)
14
+ @key = key || "default"
15
+ end
16
+
17
+ def hook
18
+ templates[key.sub(/^--/, "")]
19
+ end
20
+
21
+ def target
22
+ TARGET_HOOK_PATH
23
+ end
24
+
25
+ def install
26
+ if
27
+ hook
28
+ then
29
+ FileUtils.cp(hook, target)
30
+ FileUtils.chmod(0755, target)
31
+ puts "Installed #{hook} to #{target}"
32
+ true
33
+ else
34
+ warn "Could not find template #{key}"
35
+ false
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def templates
42
+ return @templates if @templates
43
+ pattern = File.join(TEMPLATE_DIR, "*")
44
+
45
+ @templates =
46
+ Dir.glob(pattern).inject({}) do |hash, file|
47
+ key = file.match(/\/([^\/]+?)$/)[1]
48
+ hash[key] = file
49
+ hash
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,85 @@
1
+ require 'pluginator'
2
+ require 'pre-commit/configuration'
3
+ require 'plugins/pluginator/extensions/conversions'
4
+ require 'pre-commit/plugins_list'
5
+
6
+ module PreCommit
7
+ class ListEvaluator
8
+ include Pluginator::Extensions::Conversions
9
+
10
+ attr_reader :config
11
+
12
+ def initialize(config)
13
+ @config = config
14
+ end
15
+
16
+ def list
17
+ <<-DATA
18
+ Available providers: #{config.providers.list.join(" ")}
19
+ Available checks : #{plugin_names.join(" ")}
20
+ Default checks : #{config.get_arr(:checks).join(" ")}
21
+ Enabled checks : #{checks_config.join(" ")}
22
+ Evaluated checks : #{checks_evaluated.join(" ")}
23
+ Default warnings : #{config.get_arr(:warnings).join(" ")}
24
+ Enabled warnings : #{warnings_config.join(" ")}
25
+ Evaluated warnings : #{warnings_evaluated.join(" ")}
26
+ DATA
27
+ end
28
+
29
+ def plugins
30
+ list = config.pluginator['checks'].map{|plugin| [class2string(class2name(plugin)), plugin] }.sort
31
+ separator = list.map{|name, plugin| name.length }.max
32
+ list.map{ |name, plugin| format_plugin(name, separator, plugin) }.flatten
33
+ end
34
+
35
+ def checks_config
36
+ get_combined_checks - get_arr_checks_remove
37
+ end
38
+
39
+ def checks_evaluated(type = :evaluated_names)
40
+ PreCommit::PluginsList.new(get_combined_checks, get_arr_checks_remove) do |name|
41
+ config.pluginator.find_check(name)
42
+ end.send(type)
43
+ end
44
+
45
+ def warnings_config
46
+ get_combined_warnings - get_arr_warnings_remove
47
+ end
48
+
49
+ def warnings_evaluated(type = :evaluated_names)
50
+ PreCommit::PluginsList.new(get_combined_warnings, get_arr_warnings_remove) do |name|
51
+ config.pluginator.find_check(name)
52
+ end.send(type)
53
+ end
54
+
55
+ private
56
+
57
+ def plugin_names
58
+ config.pluginator['checks'].map{|plugin| class2string(class2name(plugin)) }.sort
59
+ end
60
+
61
+ def format_plugin(name, separator, plugin)
62
+ line = [sprintf("%#{separator}s : %s", name, plugin.description)]
63
+ line << sprintf("%#{separator}s - includes: %s", "", plugin.includes.join(" ")) if plugin.respond_to?(:includes)
64
+ line << sprintf("%#{separator}s - excludes: %s", "", plugin.excludes.join(" ")) if plugin.respond_to?(:excludes)
65
+ line
66
+ end
67
+
68
+ def get_combined_checks
69
+ @get_combined_checks ||= config.get_combined(:checks)
70
+ end
71
+
72
+ def get_arr_checks_remove
73
+ @get_arr_checks_remove ||= config.get_arr("checks_remove")
74
+ end
75
+
76
+ def get_combined_warnings
77
+ @get_combined_warnings ||= config.get_combined(:warnings)
78
+ end
79
+
80
+ def get_arr_warnings_remove
81
+ @get_arr_warnings_remove ||= config.get_arr("warnings_remove")
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,87 @@
1
+ module PreCommit
2
+
3
+ def self.pluginator
4
+ Pluginator.find('pre_commit', :extends => [:find_check])
5
+ end
6
+
7
+ class PluginsList
8
+ attr_reader :configured_names, :configured_remove
9
+
10
+ def initialize(configured_names, configured_remove, &block)
11
+ @configured_names = configured_names
12
+ @configured_remove = configured_remove
13
+ @class_finder = block
14
+ end
15
+
16
+ def evaluated_names
17
+ evaluated_names_(evaluated_names_pairs).flatten.compact
18
+ end
19
+
20
+ def list_to_run
21
+ list_to_run_(evaluated_names_pairs).flatten.compact
22
+ end
23
+
24
+ private
25
+
26
+ def evaluated_names_(list)
27
+ list.map{|name, klass, includes| [name] + evaluated_names_(includes||[]) }
28
+ end
29
+
30
+ def list_to_run_(list)
31
+ list.map{|name, klass, includes| [klass] + list_to_run_(includes||[]) }
32
+ end
33
+
34
+ def evaluated_names_pairs
35
+ list = find_classes_and_includes(configured_names)
36
+ excludes = excludes(list).flatten.compact
37
+ list = filter_excludes(list, excludes)
38
+ list = filter_excludes(list, configured_remove_aliases)
39
+ list = filter_callable(list)
40
+ list
41
+ end
42
+
43
+ def find_classes_and_includes(list)
44
+ find_classes(list).map{ |name, klass| class_and_includes(name, klass) }
45
+ end
46
+
47
+ def find_class(name)
48
+ @class_finder.call(name)
49
+ end
50
+
51
+ def find_classes(list)
52
+ list.map{|name| [name, find_class(name)] }.reject{|name, klass| klass.nil? }
53
+ end
54
+
55
+ def class_and_includes(name, klass)
56
+ [ name, klass, klass.respond_to?(:includes) ? find_classes_and_includes(klass.includes) : [] ]
57
+ end
58
+
59
+ def excludes(list)
60
+ list.map{|name, klass, includes| class_excludes(klass) + excludes(includes) }
61
+ end
62
+
63
+ def class_excludes(klass)
64
+ klass.respond_to?(:excludes) ? klass.excludes : []
65
+ end
66
+
67
+ def filter_excludes(list, excludes)
68
+ list.map{|name, klass, includes| excludes.include?(name) ? nil : [name, klass, filter_excludes(includes, excludes)] }.compact
69
+ end
70
+
71
+ def filter_callable(list)
72
+ list.map{|name, klass, includes|
73
+ (klass.instance_methods.include?(:call) ? [name, klass] : [nil, nil]) << filter_callable(includes)
74
+ }.compact
75
+ end
76
+
77
+ def configured_remove_aliases
78
+ @configured_remove_aliases ||= configured_remove.map{|remove|
79
+ list = [remove]
80
+ klass = find_class(remove)
81
+ list += klass.aliases if klass.respond_to?(:aliases)
82
+ list
83
+ }.flatten.compact
84
+ end
85
+
86
+ end
87
+ end
@@ -1,20 +1,65 @@
1
+ require 'pluginator'
2
+ require 'pre-commit/utils/staged_files'
3
+ require 'pre-commit/configuration'
4
+ require 'pre-commit/list_evaluator'
5
+
1
6
  module PreCommit
2
7
  class Runner
8
+ include PreCommit::Utils::StagedFiles
3
9
 
4
- def run
5
- checks_to_run = PreCommit.checks_to_run
10
+ attr_reader :pluginator, :config
6
11
 
7
- all_passed = checks_to_run.inject(true) do |current_status, check|
8
- passed = check.call
12
+ def initialize(stderr = nil, staged_files = nil, config = nil, pluginator = nil)
13
+ @stderr = (stderr or $stderr)
14
+ @pluginator = (pluginator or PreCommit.pluginator)
15
+ @config = (config or PreCommit::Configuration.new(@pluginator))
16
+ @staged_files = staged_files
17
+ end
9
18
 
10
- if !passed && check.respond_to?(:error_message)
11
- puts check.error_message
12
- end
19
+ def run
20
+ run_single(:warnings)
21
+ run_single(:checks ) or return false
22
+ true
23
+ end
13
24
 
14
- check && current_status
25
+ def run_single(name)
26
+ show_output(name, execute(list_to_run(name)))
27
+ end
28
+
29
+ def show_output(name, list)
30
+ if list.any?
31
+ @stderr.puts send(name, list)
32
+ return false
15
33
  end
34
+ true
35
+ end
36
+
37
+ def execute(list)
38
+ list.map{|cmd| cmd.new(pluginator, config, list).call(staged_files.dup) }.compact
39
+ end
40
+
41
+ def list_to_run(name)
42
+ list_evaluator.send(:"#{name}_evaluated", :list_to_run)
43
+ end
44
+
45
+ def list_evaluator
46
+ @list_evaluator ||= PreCommit::ListEvaluator.new(config)
47
+ end
48
+
49
+ def warnings(list)
50
+ <<-WARNINGS
51
+ pre-commit: Some warnings were raised. These will not stop commit:
52
+ #{list.join("\n")}
53
+ WARNINGS
54
+ end
55
+
56
+ def checks(list)
57
+ <<-ERRORS
58
+ pre-commit: Stopping commit because of errors.
59
+ #{list.join("\n")}
60
+ pre-commit: You can bypass this check using `git commit -n`
16
61
 
17
- exit(all_passed ? 0 : 1)
62
+ ERRORS
18
63
  end
19
64
 
20
65
  end