pre-commit 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +39 -16
- data/bin/pre-commit +1 -12
- data/lib/plugins/pluginator/extensions/find_check.rb +26 -0
- data/lib/plugins/pre_commit/checks/before_all.rb +23 -7
- data/lib/plugins/pre_commit/checks/ci.rb +10 -3
- data/lib/plugins/pre_commit/checks/closure.rb +12 -4
- data/lib/plugins/pre_commit/checks/coffeelint.rb +9 -4
- data/lib/plugins/pre_commit/checks/common.rb +17 -0
- data/lib/plugins/pre_commit/checks/console_log.rb +23 -7
- data/lib/plugins/pre_commit/checks/csslint.rb +32 -0
- data/lib/plugins/pre_commit/checks/debugger.rb +14 -10
- data/lib/plugins/pre_commit/checks/gemfile_path.rb +18 -7
- data/lib/plugins/pre_commit/checks/jshint.rb +10 -4
- data/lib/plugins/pre_commit/checks/jslint.rb +11 -5
- data/lib/plugins/pre_commit/checks/local.rb +10 -2
- data/lib/plugins/pre_commit/checks/merge_conflict.rb +15 -6
- data/lib/plugins/pre_commit/checks/migration.rb +32 -26
- data/lib/plugins/pre_commit/checks/nb_space.rb +10 -2
- data/lib/plugins/pre_commit/checks/php.rb +10 -4
- data/lib/plugins/pre_commit/checks/pry.rb +15 -6
- data/lib/plugins/pre_commit/checks/rails.rb +17 -0
- data/lib/plugins/pre_commit/checks/rspec_focus.rb +19 -7
- data/lib/plugins/pre_commit/checks/rubocop.rb +20 -8
- data/lib/plugins/pre_commit/checks/ruby.rb +17 -0
- data/lib/plugins/pre_commit/checks/ruby_symbol_hashrockets.rb +17 -8
- data/lib/plugins/pre_commit/checks/tabs.rb +15 -8
- data/lib/plugins/pre_commit/checks/whitespace.rb +28 -5
- data/lib/plugins/pre_commit/configuration/providers/README.md +10 -0
- data/lib/plugins/pre_commit/configuration/providers/default.rb +34 -0
- data/lib/plugins/pre_commit/configuration/providers/git.rb +26 -0
- data/lib/plugins/pre_commit/configuration/providers/git_old.rb +28 -0
- data/lib/plugins/pre_commit/configuration/providers/yaml.rb +67 -0
- data/lib/pre-commit.rb +28 -1
- data/lib/pre-commit/checks.rb +1 -98
- data/lib/pre-commit/checks/grep.rb +57 -0
- data/lib/{plugins/pre_commit → pre-commit}/checks/js.rb +15 -7
- data/lib/pre-commit/checks/plugin.rb +13 -0
- data/lib/pre-commit/cli.rb +46 -19
- data/lib/pre-commit/configuration.rb +54 -0
- data/lib/pre-commit/configuration/providers.rb +53 -0
- data/lib/pre-commit/installer.rb +54 -0
- data/lib/pre-commit/list_evaluator.rb +85 -0
- data/lib/pre-commit/plugins_list.rb +87 -0
- data/lib/pre-commit/runner.rb +54 -9
- data/lib/pre-commit/support/csslint/csslint.js +9259 -0
- data/lib/pre-commit/utils/git_conversions.rb +56 -0
- data/lib/pre-commit/utils/staged_files.rb +21 -0
- metadata +47 -30
- data/lib/pre-commit/support/templates/automatic_hook +0 -35
- data/lib/pre-commit/support/templates/default_hook +0 -35
- data/lib/pre-commit/support/templates/manual_hook +0 -14
- data/lib/pre-commit/utils.rb +0 -27
data/lib/pre-commit/cli.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
12
|
+
def initialize(*args)
|
13
|
+
@args = args
|
14
|
+
end
|
11
15
|
|
12
|
-
|
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
|
15
|
-
|
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
|
19
|
-
key
|
20
|
-
|
34
|
+
def execute_install(key = nil, *args)
|
35
|
+
PreCommit::Installer.new(key).install
|
36
|
+
end
|
21
37
|
|
22
|
-
|
38
|
+
def execute_list(*args)
|
39
|
+
puts list_evaluator.list
|
40
|
+
true
|
41
|
+
end
|
23
42
|
|
24
|
-
|
25
|
-
|
43
|
+
def execute_plugins(*args)
|
44
|
+
puts list_evaluator.plugins
|
45
|
+
true
|
26
46
|
end
|
27
47
|
|
28
|
-
|
48
|
+
def execute_enable(*args)
|
49
|
+
config.enable(*args)
|
50
|
+
rescue ArgumentError
|
51
|
+
execute_help('enable', *args)
|
52
|
+
end
|
29
53
|
|
30
|
-
def
|
31
|
-
|
54
|
+
def execute_disable(*args)
|
55
|
+
config.disable(*args)
|
56
|
+
rescue ArgumentError
|
57
|
+
execute_help('disable', *args)
|
58
|
+
end
|
32
59
|
|
33
|
-
|
34
|
-
|
35
|
-
|
60
|
+
def config
|
61
|
+
@config ||= PreCommit::Configuration.new(PreCommit.pluginator)
|
62
|
+
end
|
36
63
|
|
37
|
-
|
38
|
-
|
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
|
data/lib/pre-commit/runner.rb
CHANGED
@@ -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
|
-
|
5
|
-
checks_to_run = PreCommit.checks_to_run
|
10
|
+
attr_reader :pluginator, :config
|
6
11
|
|
7
|
-
|
8
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
19
|
+
def run
|
20
|
+
run_single(:warnings)
|
21
|
+
run_single(:checks ) or return false
|
22
|
+
true
|
23
|
+
end
|
13
24
|
|
14
|
-
|
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
|
-
|
62
|
+
ERRORS
|
18
63
|
end
|
19
64
|
|
20
65
|
end
|