checker 0.0.1 → 0.7.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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.travis.yml +13 -0
- data/CHANGELOG +103 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +64 -0
- data/LICENCE +21 -0
- data/README.md +142 -0
- data/Rakefile +4 -0
- data/bin/checker +1 -0
- data/checker.gemspec +11 -4
- data/lib/checker.rb +28 -3
- data/lib/checker/cli.rb +88 -4
- data/lib/checker/core_ext.rb +25 -2
- data/lib/checker/helper.rb +20 -0
- data/lib/checker/installator.rb +65 -0
- data/lib/checker/modules/base.rb +224 -0
- data/lib/checker/modules/coffeescript.rb +22 -0
- data/lib/checker/modules/conflict.rb +20 -0
- data/lib/checker/modules/console_log.rb +20 -0
- data/lib/checker/modules/haml.rb +12 -14
- data/lib/checker/modules/javascript.rb +32 -0
- data/lib/checker/modules/pry.rb +20 -0
- data/lib/checker/modules/rubocop.rb +17 -0
- data/lib/checker/modules/ruby.rb +5 -21
- data/lib/checker/modules/sass.rb +80 -0
- data/lib/checker/modules/slim.rb +21 -0
- data/lib/checker/modules/yaml.rb +19 -0
- data/lib/checker/options.rb +22 -0
- data/lib/checker/result.rb +21 -0
- data/lib/checker/results/console_log.rb +13 -0
- data/lib/checker/results/default.rb +13 -0
- data/lib/checker/results/javascript.rb +24 -0
- data/lib/checker/results/rubocop.rb +6 -0
- data/lib/checker/rvm.rb +16 -0
- data/lib/checker/version.rb +3 -0
- data/spec/assets/stylesheets/empty +0 -0
- data/spec/checker/cli_spec.rb +37 -0
- data/spec/checker/fixtures/conflict/with_conflict.rb +5 -0
- data/spec/checker/fixtures/conflict/without_conflict.rb +2 -0
- data/spec/checker/fixtures/console_log/with_console_log.js +3 -0
- data/spec/checker/fixtures/console_log/without_console_log.js +2 -0
- data/spec/checker/fixtures/pry/with_both.rb +4 -0
- data/spec/checker/fixtures/pry/with_pry.rb +3 -0
- data/spec/checker/fixtures/pry/with_pry_remote.rb +3 -0
- data/spec/checker/fixtures/pry/without_pry.rb +2 -0
- data/spec/checker/fixtures/ruby/bad.rb +2 -0
- data/spec/checker/fixtures/ruby/good.rb +3 -0
- data/spec/checker/fixtures/yaml/bad.yaml +18 -0
- data/spec/checker/fixtures/yaml/good.yaml +18 -0
- data/spec/checker/modules/base_spec.rb +53 -0
- data/spec/checker/modules/coffeescript_spec.rb +16 -0
- data/spec/checker/modules/conflict_spec.rb +23 -0
- data/spec/checker/modules/console_log_spec.rb +49 -0
- data/spec/checker/modules/haml_spec.rb +18 -0
- data/spec/checker/modules/javascript_spec.rb +69 -0
- data/spec/checker/modules/pry_spec.rb +35 -0
- data/spec/checker/modules/ruby_spec.rb +26 -0
- data/spec/checker/modules/sass_spec.rb +101 -0
- data/spec/checker/modules/slim_spec.rb +18 -0
- data/spec/checker/modules/yaml_spec.rb +27 -0
- data/spec/spec_helper.rb +27 -0
- data/templates/checker-prepare-commit-msg +15 -0
- metadata +125 -15
- data/README +0 -4
- data/lib/checker/cli/execute.rb +0 -61
- data/lib/checker/modules/all.rb +0 -16
- data/lib/checker/utils.rb +0 -48
data/lib/checker/cli.rb
CHANGED
@@ -1,11 +1,95 @@
|
|
1
1
|
require 'checker'
|
2
|
-
require 'checker/cli/execute'
|
3
2
|
|
4
3
|
module Checker
|
5
|
-
module Modules; end
|
6
|
-
|
7
4
|
class CLI
|
5
|
+
class << self
|
6
|
+
def execute
|
7
|
+
directory_to_check = nil
|
8
|
+
|
9
|
+
if ARGV.size == 0
|
10
|
+
modules = get_modules_to_check
|
11
|
+
else
|
12
|
+
if ARGV[0] == "install"
|
13
|
+
Checker::Installator.install!
|
14
|
+
elsif ARGV[0] == "reinstall"
|
15
|
+
Checker::Installator.reinstall!
|
16
|
+
elsif ARGV[0] == "help"
|
17
|
+
Checker::Helper.show_help!
|
18
|
+
elsif ARGV[0] == "modules"
|
19
|
+
Checker::Helper.show_modules!(self.available_modules)
|
20
|
+
elsif File.exist?(ARGV[0]) && File.directory?(ARGV[0])
|
21
|
+
directory_to_check = ARGV[0].gsub /\/+$/, ''
|
22
|
+
modules = 'all'
|
23
|
+
else
|
24
|
+
modules = ARGV.map(&:downcase)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if modules.empty? || modules.include?('all')
|
29
|
+
modules = available_modules
|
30
|
+
end
|
31
|
+
|
32
|
+
check_module_availability(modules) do |result|
|
33
|
+
puts "Modules not available: #{result.join(", ")}.\n"
|
34
|
+
puts "Available: all, #{available_modules.join(", ")}\n"
|
35
|
+
puts "Check your git config checker.check\n"
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
module_instances = []
|
40
|
+
if !directory_to_check.nil?
|
41
|
+
files = Dir["#{directory_to_check}/**/*"]
|
42
|
+
else
|
43
|
+
files = modified_files
|
44
|
+
end
|
45
|
+
modules.each do |mod|
|
46
|
+
klass = "Checker::Modules::#{mod.classify}".constantize
|
47
|
+
module_instances << klass.new(files.dup)
|
48
|
+
end
|
49
|
+
|
50
|
+
files_checked = module_instances.map(&:files_to_check).flatten.uniq
|
51
|
+
puts "[ CHECKER #{Checker::VERSION} - #{files_checked.size} files ]".light_blue
|
52
|
+
|
53
|
+
results = module_instances.map(&:check)
|
54
|
+
show_full_status module_instances
|
55
|
+
exit (results.all_true? ? 0 : 1)
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
def available_modules
|
60
|
+
Checker::Modules.constants.map(&:to_s).map(&:underscore) - ['base']
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_module_availability(modules)
|
64
|
+
result = modules - available_modules
|
65
|
+
unless result.empty?
|
66
|
+
if block_given?
|
67
|
+
yield(result)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_modules_to_check
|
73
|
+
Checker::Options.modules_to_check
|
74
|
+
end
|
75
|
+
|
76
|
+
def modified_files
|
77
|
+
@modified_files ||= `git status --porcelain | egrep "^(A|M|R).*" | awk ' { if ($3 == "->") print $4; else print $2 } '`.split
|
78
|
+
end
|
8
79
|
|
9
|
-
|
80
|
+
def show_full_status modules
|
81
|
+
full_status = {:total => 0, :ok => 0, :warning => 0, :fail => 0}
|
82
|
+
modules.each do |m|
|
83
|
+
full_status = full_status.merge(m.full_results) { |k, v1, v2| v1 + v2 }
|
84
|
+
end
|
85
|
+
puts "-" * 80
|
86
|
+
print "#{full_status[:total]} checks preformed, "
|
87
|
+
print "#{full_status[:ok]} ok".green
|
88
|
+
print ", "
|
89
|
+
print "#{full_status[:warning]} warning".magenta
|
90
|
+
print ", "
|
91
|
+
puts "#{full_status[:fail]} fail".red
|
92
|
+
end
|
93
|
+
end
|
10
94
|
end
|
11
95
|
end
|
data/lib/checker/core_ext.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'checker/utils'
|
2
|
-
|
3
1
|
class CoreExt
|
4
2
|
def self.constantize(camel_cased_word)
|
5
3
|
names = camel_cased_word.split('::')
|
@@ -11,6 +9,23 @@ class CoreExt
|
|
11
9
|
end
|
12
10
|
constant
|
13
11
|
end
|
12
|
+
|
13
|
+
def self.classify(underscored_word)
|
14
|
+
words = underscored_word.split("_")
|
15
|
+
words.each do |word|
|
16
|
+
word.capitalize!
|
17
|
+
end.join("")
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.underscore(camel_cased_word)
|
21
|
+
word = camel_cased_word.to_s.dup
|
22
|
+
word.gsub!(/::/, '/')
|
23
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
24
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
25
|
+
word.tr!("-", "_")
|
26
|
+
word.downcase!
|
27
|
+
word
|
28
|
+
end
|
14
29
|
end
|
15
30
|
|
16
31
|
class String
|
@@ -18,6 +33,14 @@ class String
|
|
18
33
|
CoreExt.constantize(self)
|
19
34
|
end
|
20
35
|
|
36
|
+
def classify
|
37
|
+
CoreExt.classify(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def underscore
|
41
|
+
CoreExt.underscore(self)
|
42
|
+
end
|
43
|
+
|
21
44
|
def ends_with?(patt)
|
22
45
|
patt = Regexp.new(Regexp.escape(patt) + "$")
|
23
46
|
self.match patt
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Checker
|
2
|
+
class Helper
|
3
|
+
def self.show_help!
|
4
|
+
puts "Checker version #{Checker::VERSION}"
|
5
|
+
puts "* install - type 'checker install' to install git pre-commit-hook"
|
6
|
+
puts "* reinstall - type 'checker reinstall' to purge current hook git pre-commit-hook and install new one"
|
7
|
+
puts "* modules - type 'checker modules' to see available modules"
|
8
|
+
puts "* checks - type 'checker [module name]' to check your current git stage"
|
9
|
+
puts "* [dir] - type 'checker [directory]' to check all files in specified directory"
|
10
|
+
puts " ex. 'checker lib/'; 'checker .' etc"
|
11
|
+
puts "* help - type 'checker help' to see this message :)"
|
12
|
+
exit 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.show_modules!(modules)
|
16
|
+
puts "Available modules are: all, #{modules.join(", ")}"
|
17
|
+
exit 0
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Checker
|
2
|
+
class Installator
|
3
|
+
def self.template
|
4
|
+
dir = File.expand_path('../../..', __FILE__)
|
5
|
+
temp = File.read(File.join(dir, "/templates/checker-prepare-commit-msg"))
|
6
|
+
ERB.new(temp).result
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.hooks_dir
|
10
|
+
"#{Dir.pwd}/.git/hooks"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.check_hook!
|
14
|
+
unless Dir.exist?(hooks_dir)
|
15
|
+
puts "Git Hooks dir not found. Are you sure you are inside project with git?"
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.reinstall!
|
21
|
+
check_hook!
|
22
|
+
|
23
|
+
pre_commit = "#{hooks_dir}/prepare-commit-msg"
|
24
|
+
if File.exists?(pre_commit)
|
25
|
+
puts "Removing current git precommit hook..."
|
26
|
+
File.delete(pre_commit)
|
27
|
+
end
|
28
|
+
|
29
|
+
install!
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.install!
|
33
|
+
check_hook!
|
34
|
+
|
35
|
+
pre_commit = "#{hooks_dir}/prepare-commit-msg"
|
36
|
+
if File.exist?(pre_commit)
|
37
|
+
puts "Appending checker script to existing prepare-commit-msg hook..."
|
38
|
+
begin
|
39
|
+
open(pre_commit, 'a') do |f|
|
40
|
+
f.puts(self.template)
|
41
|
+
f.chmod(0755)
|
42
|
+
end
|
43
|
+
rescue Exception => e
|
44
|
+
puts "Couldn't append checker script: #{e.message}"
|
45
|
+
exit 1
|
46
|
+
end
|
47
|
+
exit 0
|
48
|
+
else
|
49
|
+
tmp = self.template
|
50
|
+
str = "#!/bin/bash \n #{tmp}"
|
51
|
+
begin
|
52
|
+
open(pre_commit, "w") do |f|
|
53
|
+
f.puts(str)
|
54
|
+
f.chmod(0755)
|
55
|
+
end
|
56
|
+
rescue Exception => e
|
57
|
+
puts "Couldn't write checker script: #{e.message}"
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
puts "Script installed!"
|
61
|
+
exit 0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
module Checker
|
2
|
+
module Modules
|
3
|
+
class Base
|
4
|
+
attr_accessor :files, :full_results
|
5
|
+
|
6
|
+
def initialize(file_list = nil)
|
7
|
+
self.files = file_list
|
8
|
+
self.full_results = {:total => 0, :ok => 0, :warning => 0, :fail => 0}
|
9
|
+
end
|
10
|
+
|
11
|
+
def check
|
12
|
+
check_files_existing or return true
|
13
|
+
print_module_header
|
14
|
+
check_executable or return true
|
15
|
+
check_all_files
|
16
|
+
valid?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
@results.all_true?
|
21
|
+
end
|
22
|
+
|
23
|
+
def files_to_check
|
24
|
+
@files_to_check ||= begin
|
25
|
+
if self.class.extensions.any?
|
26
|
+
self.files.select { |f|
|
27
|
+
self.class.extensions.map { |ex| f.ends_with?(".#{ex}") }.any?
|
28
|
+
}
|
29
|
+
else
|
30
|
+
self.files
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def classname
|
36
|
+
self.class.to_s.split('::').last
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def print_module_header
|
42
|
+
color "[ #{name} - #{files_to_check.size} files ]\n", :light_blue
|
43
|
+
end
|
44
|
+
|
45
|
+
def dependency_message
|
46
|
+
"Executable not found, skipping...\n"
|
47
|
+
end
|
48
|
+
|
49
|
+
def check_files_existing
|
50
|
+
files_to_check.any?
|
51
|
+
end
|
52
|
+
|
53
|
+
def check_executable
|
54
|
+
if check_for_executable
|
55
|
+
true
|
56
|
+
else
|
57
|
+
color dependency_message, :magenta
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_for_executable
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_all_files
|
67
|
+
with_checker_cache do
|
68
|
+
@results = files_to_check.map do |file_name|
|
69
|
+
gather_result :total
|
70
|
+
color " Checking #{file_name}...", :yellow
|
71
|
+
result = check_one_file(file_name)
|
72
|
+
show_status result.status
|
73
|
+
gather_result result.status
|
74
|
+
flush_and_forget_output result.status
|
75
|
+
result.success?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def check_one(filename, options = {})
|
81
|
+
puts "Called from #{self.class} - extend me in here!"
|
82
|
+
false
|
83
|
+
end
|
84
|
+
|
85
|
+
def check_one_file file_name
|
86
|
+
checksum = ::Digest::MD5.hexdigest(file_name)
|
87
|
+
debug(file_name)
|
88
|
+
checkout_file(file_name, checksum)
|
89
|
+
check_one(checkout_file_name(checksum), :extension => File.extname(file_name))
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.extensions *args
|
93
|
+
@extensions ||= []
|
94
|
+
if args.empty?
|
95
|
+
@extensions
|
96
|
+
else
|
97
|
+
@extensions += args
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def gather_result result
|
102
|
+
self.full_results[result] += 1
|
103
|
+
end
|
104
|
+
|
105
|
+
def plain_command(cmd, options = {})
|
106
|
+
cmd = parse_command(cmd, options)
|
107
|
+
execute(cmd, options)
|
108
|
+
end
|
109
|
+
|
110
|
+
def silent_command(cmd, options = {})
|
111
|
+
options = { :output => false, :return_boolean => true }.merge(options)
|
112
|
+
cmd = parse_command(cmd, options)
|
113
|
+
execute(cmd, options)
|
114
|
+
end
|
115
|
+
|
116
|
+
def flush_and_forget_output(status)
|
117
|
+
print @buffer.to_s if (status == :warning or status == :fail)
|
118
|
+
@buffer = ""
|
119
|
+
end
|
120
|
+
|
121
|
+
def print_success_message
|
122
|
+
puts " [OK]".green
|
123
|
+
end
|
124
|
+
|
125
|
+
def print_warning_message
|
126
|
+
puts " [WARNING]".magenta
|
127
|
+
end
|
128
|
+
|
129
|
+
def print_fail_message
|
130
|
+
puts " [FAIL]".red
|
131
|
+
end
|
132
|
+
|
133
|
+
def show_status(status)
|
134
|
+
if status == :ok
|
135
|
+
print_success_message
|
136
|
+
elsif status == :warning
|
137
|
+
print_warning_message
|
138
|
+
else
|
139
|
+
print_fail_message
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def execute(cmd, options = {})
|
144
|
+
debug("executing: #{cmd}")
|
145
|
+
io = IO.popen(cmd)
|
146
|
+
Process.wait(io.pid)
|
147
|
+
@buffer ||= ""
|
148
|
+
@buffer << io.read
|
149
|
+
options[:return_boolean] ? success? : exitstatus
|
150
|
+
end
|
151
|
+
|
152
|
+
def exitstatus
|
153
|
+
$? && $?.exitstatus
|
154
|
+
end
|
155
|
+
|
156
|
+
def success?
|
157
|
+
$? && $?.success?
|
158
|
+
end
|
159
|
+
|
160
|
+
def parse_command command, options
|
161
|
+
options = { :bundler => true, :output => true, :rvm => true }.merge(options)
|
162
|
+
command = bundler_command(command) if use_bundler? && options[:bundler]
|
163
|
+
command = rvm_command(command) if use_rvm? && options[:rvm]
|
164
|
+
command << " > /dev/null" unless options[:output]
|
165
|
+
"#{command} 2>&1"
|
166
|
+
end
|
167
|
+
|
168
|
+
def color(str, color)
|
169
|
+
print str.colorize(color) if str.length > 0
|
170
|
+
end
|
171
|
+
|
172
|
+
def name
|
173
|
+
classname.underscore.upcase
|
174
|
+
end
|
175
|
+
|
176
|
+
def use_bundler?
|
177
|
+
File.exists?("Gemfile.lock")
|
178
|
+
end
|
179
|
+
|
180
|
+
def bundler_command(command)
|
181
|
+
"bundle exec #{command}"
|
182
|
+
end
|
183
|
+
|
184
|
+
def use_rvm?
|
185
|
+
File.exists?(rvm_shell)
|
186
|
+
end
|
187
|
+
|
188
|
+
def rails_project?
|
189
|
+
use_bundler? && File.read("Gemfile.lock").match(/ rails /)
|
190
|
+
end
|
191
|
+
|
192
|
+
def rails_with_ap?
|
193
|
+
rails_project? && File.exists?("app/assets")
|
194
|
+
end
|
195
|
+
|
196
|
+
def rvm_command(command)
|
197
|
+
Checker::RVM.rvm_command(command)
|
198
|
+
end
|
199
|
+
|
200
|
+
def rvm_shell
|
201
|
+
Checker::RVM.rvm_shell
|
202
|
+
end
|
203
|
+
|
204
|
+
def with_checker_cache
|
205
|
+
begin
|
206
|
+
`mkdir .checker-cache`
|
207
|
+
yield if block_given?
|
208
|
+
ensure
|
209
|
+
`rm -rf .checker-cache > /dev/null 2>&1`
|
210
|
+
## for sass check
|
211
|
+
`rm -rf app/assets/stylesheets/checker-cache*` if rails_with_ap?
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def checkout_file file_name, target
|
216
|
+
`git show :0:#{file_name} > #{checkout_file_name(target)} 2>/dev/null`
|
217
|
+
end
|
218
|
+
|
219
|
+
def checkout_file_name target
|
220
|
+
".checker-cache/#{target}"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|