|
#!/usr/bin/env ruby |
|
|
|
require 'rubocop' |
|
|
|
module DirtyCop |
|
extend self # In your face, style guide! |
|
|
|
def bury_evidence?(file, line) |
|
!report_offense_at?(file, line) |
|
end |
|
|
|
def uncovered_targets |
|
@files |
|
end |
|
|
|
def cover_up_unmodified(ref, only_changed_lines = true) |
|
@files = files_modified_since(ref) |
|
@line_filter = build_line_filter(@files, ref) if only_changed_lines |
|
end |
|
|
|
def process_bribe |
|
ref = '--staged HEAD' |
|
only_changed_lines = true |
|
|
|
cover_up_unmodified ref, only_changed_lines |
|
end |
|
|
|
private |
|
|
|
def report_offense_at?(file, line) |
|
!@line_filter || @line_filter.fetch(file)[line] |
|
end |
|
|
|
def files_modified_since(ref) |
|
`git diff --diff-filter=AM --name-only #{ref}`. |
|
lines. |
|
map(&:chomp). |
|
grep(/\.rb$/). |
|
map { |file| File.absolute_path(file) } |
|
end |
|
|
|
def build_line_filter(files, ref) |
|
result = {} |
|
|
|
suspects = files_modified_since(ref) |
|
suspects.each do |file| |
|
result[file] = lines_modified_since(file, ref) |
|
end |
|
|
|
result |
|
end |
|
|
|
def lines_modified_since(file, ref) |
|
ranges = |
|
`git diff -p -U0 #{ref} #{file}`. |
|
lines. |
|
grep(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/) { $1.to_i...($1.to_i + $2.to_i) }. |
|
reverse |
|
|
|
mask = Array.new(ranges.first.end) |
|
|
|
ranges.each do |range| |
|
range.each do |line| |
|
mask[line] = true |
|
end |
|
end |
|
|
|
mask |
|
end |
|
end |
|
|
|
module RuboCop |
|
class TargetFinder |
|
alias find_unpatched find |
|
|
|
def find(args) |
|
replacement = DirtyCop.uncovered_targets |
|
return replacement if replacement |
|
|
|
find_unpatched(args) |
|
end |
|
end |
|
|
|
class Runner |
|
alias inspect_file_unpatched inspect_file |
|
|
|
def inspect_file(file) |
|
offenses, updated = inspect_file_unpatched(file) |
|
offenses = offenses.reject { |o| DirtyCop.bury_evidence?(file.path, o.line) } |
|
[offenses, updated] |
|
end |
|
end |
|
end |
|
|
|
def print_header(header) |
|
puts "\e[33m#{header}\e[0m" |
|
end |
|
|
|
failed = false |
|
|
|
# ESLint |
|
print_header 'Strat eslint analysis...' |
|
`PATH="$(npm bin)":"$PATH"` |
|
if `which eslint` == 'eslint not found' |
|
puts 'WARNING: You need to install ESLint to lint your files (SKIP ESLint)' |
|
else |
|
files_js = `git diff --staged --name-only --diff-filter=d`.lines.map(&:chomp).grep(/\.coffee|\.js$/) |
|
files_js.each do |file| |
|
result = `git show :#{file} | eslint --stdin --stdin-filename "#{file}"` |
|
puts result |
|
failed = result.lines.count > 1 |
|
end |
|
puts '[SKIPPED] Nothing to check' if files_js.empty? |
|
end |
|
puts "\n" |
|
|
|
print_header 'Start Rubocop analysis...' |
|
if DirtyCop.process_bribe.any? |
|
failed ||= RuboCop::CLI.new.run != 0 |
|
else |
|
puts '[SKIPPED] No ruby files changed' |
|
end |
|
puts "\n" |
|
|
|
merge_branch = ENV['MERGE_BRANCH'] || 'master' |
|
staged_diff = "git diff --staged #{merge_branch} --name-only --relative --diff-filter=d" |
|
only_rb_without_specs = %x( #{staged_diff} | grep '\\.rb' | grep -v '_spec' ).gsub(/\n/, ' ') |
|
|
|
print_header 'Start yaml_check analysis...' |
|
if `which yaml_check` == 'yaml_check not found' |
|
puts 'WARNING: You need to install yaml_check (SKIP yaml_check)' |
|
else |
|
i18n_files = %x( #{staged_diff} | grep '\\/config\\/locales' | grep '\\.yml' ).gsub(/\n/, ' ') |
|
result = %x( yaml_check #{i18n_files} ) |
|
if result == '' |
|
puts '[SKIPPED] No yaml files to check' |
|
else |
|
puts result |
|
end |
|
failed ||= result.include?('[FAILED]') |
|
end |
|
puts "\n" |
|
|
|
print_header 'Start yardoc analysis...' |
|
if `which yard` == `yard not found` |
|
puts 'WARNING: You need to install yard (SKIP yard)' |
|
else |
|
if only_rb_without_specs != '' |
|
result = %x( cd `git rev-parse --show-toplevel` && yard stats --list-undoc ) |
|
puts result |
|
failed ||= !result.include?('100.00% documented') |
|
else |
|
puts '[SKIPPED] No ruby files changed' |
|
end |
|
end |
|
puts "\n" |
|
|
|
print_header 'Start flay analysis...' |
|
if `which flay` == 'flay not found' |
|
puts 'WARNING: You need to install flay (SKIP flay)' |
|
else |
|
if only_rb_without_specs != '' |
|
result = %x( flay -v --diff #{only_rb_without_specs} ) |
|
puts result |
|
else |
|
puts '[SKIPPED] No ruby files changed' |
|
end |
|
end |
|
puts "\n" |
|
|
|
print_header 'Start flog analysis...' |
|
if `which flog` == 'flog not found' |
|
puts 'WARNING: You need to install flog (SKIP flog)' |
|
else |
|
if only_rb_without_specs != '' |
|
result = %x( flog -m #{only_rb_without_specs} ) |
|
puts result |
|
else |
|
puts '[SKIPPED] No ruby files changed.' |
|
end |
|
end |
|
puts "\n" |
|
|
|
exit 1 if failed |
|
|
|
exit 0 |
This comment has been minimized.
Update: Rubocop now checks only changed lines instead of files