Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 122 lines (98 sloc) 2.51 KB
#! /usr/bin/env ruby
# Run rubocop against the files being committed, fixing what we can. Fixed offenses won't wind up
# in the commit, though, so abort if we find any offenses.
#
# Offenses in unstaged changes will currently abort the commit, but could be avoided by comparing
# the line number of the offense to those of the staged changes.
require 'json'
require 'open3'
require 'pathname'
class GitStatusLine
STATUSES = {
"A" => :added,
"B" => :pairing_broken,
"C" => :copied,
"D" => :deleted,
"M" => :modified,
"R" => :renamed,
"T" => :type_changed,
"U" => :unmerged,
"X" => :unknown
}
STATUS_LINE_REGEX = /^[#{STATUSES.keys.join("|")}]\s+/
def self.is_status_line?(line)
line =~ STATUS_LINE_REGEX
end
def self.from(line)
return nil unless is_status_line?(line)
new(line.chomp)
end
attr_reader :status
def initialize(line)
@line = line
@status = STATUSES[@line[0]]
end
def pathname
GitStatusPathname.new(@line.gsub(STATUS_LINE_REGEX, ''))
end
def added?
status == :added
end
def modified?
status == :modified
end
end
class GitStatusPathname
def initialize(filename)
@path = Pathname.new(filename)
end
def to_s
@path.to_s
end
def ruby?
@path.extname == ".rb" ||
@path.extname == ".rake" ||
@path.basename == "Gemfile"
end
end
class GitDiff
def self.status_lines
output = `git diff --cached --name-status`
output.lines.map{|l| GitStatusLine.from(l) }.compact
end
end
def changed_files
GitDiff.status_lines
.select{|f| f.added? || f.modified? }
.map(&:pathname)
.select(&:ruby?)
end
file_list = changed_files.join(" ")
if file_list == ""
puts "No files to check."
exit(0)
end
puts "Running rubocop against #{file_list}"
output, err, status = Open3.capture3("bundle exec rubocop --format json --force-exclusion --display-cop-names --auto-correct #{file_list}")
unless err.empty?
puts "Error executing Rubocop."
puts err
exit(1)
end
json = JSON.parse(output)
offenses = json["summary"]["offense_count"]
exit(0) if offenses == 0
puts "Rubocop found #{offenses} offense#{"s" if offenses > 1}. Aborting commit."
clean = true
json["files"].each do |file|
path = file["path"]
uncorrected = file["offenses"].reject{|offense| offense["corrected"] }
clean &&= uncorrected.empty?
uncorrected.each do |offense|
line = offense["location"]["line"]
message = offense["message"]
puts "#{path}:#{line} #{message}"
end
end
puts "All offenses corrected." if clean
exit(1)
You can’t perform that action at this time.