Last active
August 22, 2018 21:35
-
-
Save sonota88/980f3225ba5c95f81217a1d8c518c300 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# coding: utf-8 | |
require "pp" | |
CS_JAR_PATH = "checkstyle-8.12-all.jar" | |
CS_CONFIG_PATH = "google_checks.xml" | |
class DiffRange | |
def initialize(from, len) | |
@from = from | |
@len = len | |
end | |
def include?(n) | |
@from + 3 <= n && n < @from + @len - 3 | |
end | |
def inspect | |
"(#{@from},#{@len})" | |
end | |
end | |
class CheckstyleLine | |
attr_reader :path, :ln | |
def initialize(line) | |
if /^(.+?) (.+?):(.+?):(.+?): (.+)/ =~ line | |
@line = line | |
@level = $1 | |
@path = $2 | |
@ln = $3.to_i | |
@col = $4.to_i | |
@rest = $5 | |
@valid = true | |
else | |
@valid = false | |
end | |
end | |
def rel_path(pwd_len) | |
@path[pwd_len + 1 .. -1] | |
end | |
def to_short | |
"#{@level} #{@ln}:#{@col}: #{@rest}" | |
end | |
def valid? | |
@valid | |
end | |
end | |
# diff --git a/path/to/Foo.java b/path/to/Foo.java | |
# new file mode 100755 | |
# index 0000000..12eb909 | |
# --- /dev/null | |
# +++ b/path/to/Foo.java | |
# @@ -73,10 +73,10 @@ | |
# ... | |
def split_diff_output(git_diff_output) | |
blocks = [] | |
buf = [] | |
git_diff_output.each_line{|line| | |
line.chomp! | |
if /^diff \-\-git / =~ line | |
blocks << buf unless buf.empty? | |
buf = [line] | |
else | |
buf << line | |
end | |
} | |
blocks << buf unless buf.empty? | |
blocks | |
end | |
def extract_path(lines) | |
re = %r{^\+\+\+ b/(.+)} | |
path_line = lines.find{|line| | |
re =~ line | |
} | |
return nil unless path_line | |
re =~ path_line | |
$1 | |
end | |
def extract_diff_ranges(lines) | |
re = /^@@ \-(.+?) \+(\d+),(\d+) @@/ | |
lines.select{|line| | |
re =~ line | |
}.map{|line| | |
re =~ line | |
from = $2.to_i | |
len = $3.to_i | |
DiffRange.new(from, len) | |
} | |
end | |
def split_cs_output(cs_output) | |
blocks = [] | |
buf = [] | |
path_prev = nil | |
cs_output.each_line{|line| | |
line.chomp! | |
cs_line = CheckstyleLine.new(line) | |
next unless cs_line.valid? | |
if cs_line.path != path_prev | |
blocks << buf unless buf.empty? | |
buf = [line] | |
else | |
buf << line | |
end | |
path_prev = cs_line.path | |
} | |
blocks << buf unless buf.empty? | |
blocks | |
end | |
def select_changed(lines, diff_map) | |
cs_lines = lines.map{|line| | |
CheckstyleLine.new(line) | |
} | |
rel_path = cs_lines[0].rel_path(Dir.pwd.size) | |
cs_lines_filtered = cs_lines.select{|cs_line| | |
if diff_map.has_key?(rel_path) | |
diff_map[rel_path].any?{|dr| dr.include?(cs_line.ln) } | |
else | |
false | |
end | |
} | |
{ | |
rel_path: rel_path, | |
cs_lines: cs_lines_filtered | |
} | |
end | |
def print_result(base_commit, blocks) | |
puts "# Diff from #{base_commit}" | |
print "\n" | |
blocks.each{|block| | |
puts "## %s (%s)" % [ | |
File.basename(block[:rel_path]), | |
block[:rel_path] | |
] | |
print "\n" | |
puts "```" | |
block[:cs_lines].each{|line| | |
puts "- " + line.to_short() | |
} | |
puts "```" | |
print "\n" | |
} | |
end | |
def main(args) | |
base_commit = args[0] | |
git_diff_out = `git diff #{base_commit}` | |
# ファイルごとに分割 | |
diff_blocks = split_diff_output(git_diff_out) | |
diff_map = {} | |
diff_blocks.each{|lines| | |
path = extract_path(lines) | |
if /\.java$/ =~ path | |
diff_map[path] = extract_diff_ranges(lines) | |
end | |
} | |
file_list = diff_map.keys.join(" ") | |
cs_out = `java -jar "#{CS_JAR_PATH}" -c "#{CS_CONFIG_PATH}" #{file_list}` | |
# ファイルごとに分割 | |
cs_blocks = split_cs_output(cs_out) | |
# ファイル内での絞り込み | |
filtered_blocks = cs_blocks.map{|lines| | |
select_changed(lines, diff_map) | |
}.select{|item| | |
! item[:cs_lines].empty? | |
} | |
unless filtered_blocks.empty? | |
print_result(base_commit, filtered_blocks) | |
exit 1 | |
end | |
end | |
main(ARGV) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment