Skip to content

Commit

Permalink
Merge pull request prontolabs#34 from mmozuras/0.3.0
Browse files Browse the repository at this point in the history
0.3.0
  • Loading branch information
mmozuras committed Sep 10, 2014
2 parents cc933b1 + 122c62a commit d131d6b
Show file tree
Hide file tree
Showing 40 changed files with 572 additions and 286 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Changelog

## 0.3.0

### New features

* [#27](https://github.com/mmozuras/pronto/issues/27): '--exit-code' option for 'pronto run'. Pronto exits with non-zero code if there were any warnings/errors.
* [#16](https://github.com/mmozuras/pronto/issues/16): New formatter: GithubPullRequestFormatter. Writes review comments on GitHub pull requests.

### Changes

* [#29](https://github.com/mmozuras/pronto/issues/29): Be compatible and depend on rugged '0.21.0'.
* Performance improvement: use Rugged::Blame instead of one provided by Grit.
* Performance improvement: cache comments retrieved from GitHub.

### Bugs fixed
36 changes: 20 additions & 16 deletions lib/pronto.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
require 'rugged'
require 'pronto/rugged/diff'
require 'pronto/rugged/diff/delta'
require 'pronto/rugged/diff/patch'
require 'pronto/rugged/diff/line'
require 'pronto/rugged/tree'
require 'pronto/rugged/remote'
require 'pronto/rugged/repository'
require 'pronto/rugged/commit'
require 'octokit'
require 'forwardable'

require 'pronto/git/repository'
require 'pronto/git/patches'
require 'pronto/git/patch'
require 'pronto/git/line'
require 'pronto/git/remote'

require 'pronto/plugin'
require 'pronto/message'
require 'pronto/runner'
require 'pronto/github'

require 'pronto/formatter/text_formatter'
require 'pronto/formatter/json_formatter'
require 'pronto/formatter/github_formatter'
require 'pronto/formatter/github_pull_request_formatter'
require 'pronto/formatter/checkstyle_formatter'
require 'pronto/formatter/formatter'

module Pronto
def self.run(commit = 'master', repo_path = '.', formatter = nil)
repo = Rugged::Repository.new(repo_path)
commit ||= 'master'
merge_base = repo.merge_base(commit, repo.head.target)
patches = repo.diff(merge_base, repo.head.target)

result = run_all_runners(patches, merge_base)
repo = Git::Repository.new(repo_path)
patches = repo.diff(commit)

result = run_all_runners(patches)

formatter ||= default_formatter
formatter.format(result, repo)
puts formatter.format(result, repo)

result
end

def self.gem_names
Expand All @@ -37,7 +41,7 @@ def self.gem_names
true
elsif gem.name != 'pronto'
runner_path = File.join(gem.full_gem_path, "lib/pronto/#{gem.name}.rb")
File.exists?(runner_path)
File.exist?(runner_path)
end
end

Expand All @@ -48,9 +52,9 @@ def self.gem_names

private

def self.run_all_runners(patches, commit)
def self.run_all_runners(patches)
Runner.runners.map do |runner|
runner.new.run(patches, commit)
runner.new.run(patches, patches.commit)
end.flatten.compact
end

Expand Down
7 changes: 6 additions & 1 deletion lib/pronto/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ def is_thor_reserved_word?(word, type)

desc 'run', 'Run Pronto'

method_option :'exit-code',
type: :boolean,
banner: 'Exits with non-zero code if there were any warnings/errors.'

method_option :commit,
type: :string,
default: 'master',
Expand All @@ -39,7 +43,8 @@ def run
end

formatter = ::Pronto::Formatter.get(options[:formatter])
puts ::Pronto.run(options[:commit], '.', formatter)
messages = ::Pronto.run(options[:commit], '.', formatter)
exit(messages.count) if options[:'exit-code']
rescue Rugged::RepositoryError
puts '"pronto" should be run from a git repository'
end
Expand Down
1 change: 1 addition & 0 deletions lib/pronto/formatter/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def self.names

FORMATTERS = {
'github' => GithubFormatter,
'github_pr' => GithubPullRequestFormatter,
'json' => JsonFormatter,
'checkstyle' => CheckstyleFormatter,
'text' => TextFormatter
Expand Down
31 changes: 9 additions & 22 deletions lib/pronto/formatter/github_formatter.rb
Original file line number Diff line number Diff line change
@@ -1,44 +1,31 @@
require 'octokit'

module Pronto
module Formatter
class GithubFormatter
def format(messages, repo)
commit_messages = messages.map do |message|
github_slug = repo.remotes.map(&:github_slug).compact.first
github_slug = repo.github_slug
sha = message.commit_sha
position = message.line.commit_line.position if message.line
path = message.path
body = message.msg
path = message.path
position = message.line.commit_line.position if message.line

create_comment(github_slug, sha, position, path, body)
comment = Github::Comment.new(github_slug, sha, body, path, position)
create_comment(github_slug, sha, comment)
end

"#{commit_messages.compact.count} Pronto messages posted to GitHub"
end

private

def create_comment(repo, sha, position, path, body)
def create_comment(repo, sha, comment)
comments = client.commit_comments(repo, sha)

existing_comment = comments.find do |comment|
comment.position == position &&
comment.path == path &&
comment.body == body
end

unless existing_comment
client.create_commit_comment(repo, sha, body, path, nil, position)
end
end

def access_token
ENV['GITHUB_ACCESS_TOKEN']
existing = comments.any? { |c| comment == c }
client.create_commit_comment(repo, sha, comment) unless existing
end

def client
@client ||= Octokit::Client.new(access_token: access_token)
@client ||= Github.new
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions lib/pronto/formatter/github_pull_request_formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module Pronto
module Formatter
class GithubPullRequestFormatter
def format(messages, repo)
commit_messages = messages.map do |message|
github_slug = repo.github_slug
body = message.msg
path = message.path

commits = repo.commits_until(message.commit_sha)

line = nil
sha = commits.find do |commit|
patches = repo.show_commit(commit)
line = patches.find_line(message.full_path, message.line.new_lineno)
line
end

position = line.position - 1

comment = Github::Comment.new(github_slug, sha, body, path, position)
create_comment(github_slug, sha, comment)
end

"#{commit_messages.compact.count} Pronto messages posted to GitHub"
end

private

def create_comment(repo, sha, comment)
comments = client.pull_comments(repo, sha)
existing = comments.any? { |c| comment == c }
client.create_pull_comment(repo, sha, comment) unless existing
end

def client
@client ||= Github.new
end
end
end
end
44 changes: 44 additions & 0 deletions lib/pronto/git/line.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Pronto
module Git
class Line < Struct.new(:line, :patch, :hunk)
extend Forwardable

def_delegators :line, :addition?, :deletion?, :content, :new_lineno,
:old_lineno, :line_origin

def position
hunk_index = patch.hunks.find_index { |h| h.header == hunk.header }
line_index = patch.lines.find_index(line)

line_index + hunk_index + 1
end

def commit_sha
blame[:final_commit_id] if blame
end

def commit_line
@commit_line ||= begin
patches = patch.repo.show_commit(commit_sha)

result = patches.find_line(patch.new_file_full_path,
blame[:orig_start_line_number])
result || self # no commit_line means that it was just added
end
end

def ==(other)
content == other.content &&
line_origin == other.line_origin &&
old_lineno == other.old_lineno &&
new_lineno == other.new_lineno
end

private

def blame
@blame ||= patch.blame(new_lineno)
end
end
end
end
41 changes: 41 additions & 0 deletions lib/pronto/git/patch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module Pronto
module Git
class Patch < Struct.new(:patch, :repo)
extend Forwardable

def_delegators :patch, :delta, :hunks, :stat

def additions
stat[0]
end

def deletions
stat[1]
end

def blame(lineno)
repo.blame(self, lineno)
end

def lines
@lines ||= begin
hunks.flat_map do |hunk|
hunk.lines.map { |line| Line.new(line, self, hunk) }
end
end
end

def added_lines
lines.select(&:addition?)
end

def deleted_lines
lines.select(&:deletion?)
end

def new_file_full_path
repo.path.join(delta.new_file[:path])
end
end
end
end
24 changes: 24 additions & 0 deletions lib/pronto/git/patches.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Pronto
module Git
class Patches
include Enumerable

attr_reader :commit, :repo

def initialize(repo, commit, patches)
@commit = commit
@patches = patches.map { |patch| Git::Patch.new(patch, repo) }
end

def each(&block)
@patches.each(&block)
end

def find_line(path, line)
patch = find { |p| p.new_file_full_path == path }
lines = patch ? patch.lines : []
lines.find { |l| l.new_lineno == line }
end
end
end
end
10 changes: 10 additions & 0 deletions lib/pronto/git/remote.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Pronto
module Git
class Remote < Struct.new(:remote)
def github_slug
match = /.*github.com(:|\/)(?<slug>.*).git/.match(remote.url)
match[:slug] if match
end
end
end
end
Loading

0 comments on commit d131d6b

Please sign in to comment.