Create a gist now

Instantly share code, notes, and snippets.

Commit = Struct.new(:repo, :sha, :comment, :stats) do
def refactoring?(previous_commit)
return :spec_files_unchanged if no_changes_to_specs
return :comment if refactoring_comment
return false if result.nil? || result.failed > 0 || result.total == 0
return :spec_results_unchanged if result == previous_commit.result
return false
end
def no_changes_to_specs
!stats.any? { |s| s.path =~ /^spec/ }
end
def refactoring_comment
comment =~ /refactor/i
end
def result
@result ||= repo.test(sha)
end
end
Stat = Struct.new(:pct, :path)
Result = Struct.new(:total, :failed)
Repo = Struct.new(:path) do
def dirstat
`cd #{path} && git co master && git log --pretty=oneline --dirstat`.split("\n")
end
def test(sha)
output = `cd #{path} && git checkout #{sha} && (rake || rspec)`
results_match = output.match(/(\d+) examples, (\d+) failures/)
if results_match
total, failed = results_match.captures
Result.new(total.to_i, failed.to_i)
end
end
end
class Log
def initialize(repo_path)
@repo = Repo.new(repo_path)
end
def commits
commits = []
@repo.dirstat.each do |line|
match_commit = line.match(/^(\w+) (.*)$/)
match_stat = line.match(/([\d\.]+)\% (.*)/)
if match_commit
sha, comment = match_commit.captures
commit = Commit.new(@repo, sha, comment, [])
commits << commit
elsif match_stat
pct, path = match_stat.captures
stat = Stat.new(pct, path)
commits.last.stats << stat
else
raise "Unable to parse this line:\n#{line}"
end
end
commits
end
def refactoring_commits
result = []
commits.each_index do |index|
previous = commits[index - 1]
commit = commits[index]
reason = commit.refactoring?(previous)
result << [commit, reason] if reason
end
result
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment