Commit 03440eed authored by Ahmad Sherif's avatar Ahmad Sherif

Migrate blame loading to Gitaly

Closes gitaly#421
parent 8f9b658e
...@@ -391,7 +391,7 @@ gem 'vmstat', '~> 2.3.0' ...@@ -391,7 +391,7 @@ gem 'vmstat', '~> 2.3.0'
gem 'sys-filesystem', '~> 1.1.6' gem 'sys-filesystem', '~> 1.1.6'
# Gitaly GRPC client # Gitaly GRPC client
gem 'gitaly', '~> 0.23.0' gem 'gitaly', '~> 0.24.0'
gem 'toml-rb', '~> 0.3.15', require: false gem 'toml-rb', '~> 0.3.15', require: false
......
...@@ -269,7 +269,7 @@ GEM ...@@ -269,7 +269,7 @@ GEM
po_to_json (>= 1.0.0) po_to_json (>= 1.0.0)
rails (>= 3.2.0) rails (>= 3.2.0)
gherkin-ruby (0.3.2) gherkin-ruby (0.3.2)
gitaly (0.23.0) gitaly (0.24.0)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
grpc (~> 1.0) grpc (~> 1.0)
github-linguist (4.7.6) github-linguist (4.7.6)
...@@ -978,7 +978,7 @@ DEPENDENCIES ...@@ -978,7 +978,7 @@ DEPENDENCIES
gettext (~> 3.2.2) gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0) gettext_i18n_rails_js (~> 1.2.0)
gitaly (~> 0.23.0) gitaly (~> 0.24.0)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.5.1) gitlab-markup (~> 1.5.1)
......
# Gitaly note: JV: needs 1 RPC for #load_blame.
module Gitlab module Gitlab
module Git module Git
class Blame class Blame
...@@ -26,15 +24,29 @@ module Gitlab ...@@ -26,15 +24,29 @@ module Gitlab
private private
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/376
def load_blame def load_blame
cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{@repo.path} blame -p #{@sha} -- #{@path}) raw_output = @repo.gitaly_migrate(:blame) do |is_enabled|
# Read in binary mode to ensure ASCII-8BIT if is_enabled
raw_output = IO.popen(cmd, 'rb') {|io| io.read } load_blame_by_gitaly
else
load_blame_by_shelling_out
end
end
output = encode_utf8(raw_output) output = encode_utf8(raw_output)
process_raw_blame output process_raw_blame output
end end
def load_blame_by_gitaly
@repo.gitaly_commit_client.raw_blame(@sha, @path)
end
def load_blame_by_shelling_out
cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{@repo.path} blame -p #{@sha} -- #{@path})
# Read in binary mode to ensure ASCII-8BIT
IO.popen(cmd, 'rb') {|io| io.read }
end
def process_raw_blame(output) def process_raw_blame(output)
lines, final = [], [] lines, final = [], []
info, commits = {}, {} info, commits = {}, {}
......
...@@ -683,6 +683,14 @@ module Gitlab ...@@ -683,6 +683,14 @@ module Gitlab
@gitaly_repository_client ||= Gitlab::GitalyClient::RepositoryService.new(self) @gitaly_repository_client ||= Gitlab::GitalyClient::RepositoryService.new(self)
end end
def gitaly_migrate(method, &block)
Gitlab::GitalyClient.migrate(method, &block)
rescue GRPC::NotFound => e
raise NoRepository.new(e)
rescue GRPC::BadStatus => e
raise CommandError.new(e)
end
private private
# Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'. # Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'.
...@@ -1017,14 +1025,6 @@ module Gitlab ...@@ -1017,14 +1025,6 @@ module Gitlab
raw_output.to_i raw_output.to_i
end end
def gitaly_migrate(method, &block)
Gitlab::GitalyClient.migrate(method, &block)
rescue GRPC::NotFound => e
raise NoRepository.new(e)
rescue GRPC::BadStatus => e
raise CommandError.new(e)
end
end end
end end
end end
...@@ -128,6 +128,17 @@ module Gitlab ...@@ -128,6 +128,17 @@ module Gitlab
response.languages.map { |l| { value: l.share.round(2), label: l.name, color: l.color, highlight: l.color } } response.languages.map { |l| { value: l.share.round(2), label: l.name, color: l.color, highlight: l.color } }
end end
def raw_blame(revision, path)
request = Gitaly::RawBlameRequest.new(
repository: @gitaly_repo,
revision: revision,
path: path
)
response = GitalyClient.call(@repository.storage, :commit_service, :raw_blame, request)
response.reduce("") { |memo, msg| memo << msg.data }
end
private private
def commit_diff_request_params(commit, options = {}) def commit_diff_request_params(commit, options = {})
......
...@@ -7,63 +7,73 @@ describe Gitlab::Git::Blame, seed_helper: true do ...@@ -7,63 +7,73 @@ describe Gitlab::Git::Blame, seed_helper: true do
Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md") Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md")
end end
context "each count" do shared_examples 'blaming a file' do
it do context "each count" do
data = [] it do
blame.each do |commit, line| data = []
data << { blame.each do |commit, line|
commit: commit, data << {
line: line commit: commit,
} line: line
end }
end
expect(data.size).to eq(95)
expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit)
expect(data.first[:line]).to eq("# Contribute to GitLab")
expect(data.first[:line]).to be_utf8
end
end
context "ISO-8859 encoding" do expect(data.size).to eq(95)
let(:blame) do expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit)
Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt") expect(data.first[:line]).to eq("# Contribute to GitLab")
expect(data.first[:line]).to be_utf8
end
end end
it 'converts to UTF-8' do context "ISO-8859 encoding" do
data = [] let(:blame) do
blame.each do |commit, line| Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt")
data << {
commit: commit,
line: line
}
end end
expect(data.size).to eq(1) it 'converts to UTF-8' do
expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) data = []
expect(data.first[:line]).to eq("Ä ü") blame.each do |commit, line|
expect(data.first[:line]).to be_utf8 data << {
end commit: commit,
end line: line
}
end
context "unknown encoding" do expect(data.size).to eq(1)
let(:blame) do expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit)
Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt") expect(data.first[:line]).to eq("Ä ü")
expect(data.first[:line]).to be_utf8
end
end end
it 'converts to UTF-8' do context "unknown encoding" do
expect(CharlockHolmes::EncodingDetector).to receive(:detect).and_return(nil) let(:blame) do
data = [] Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt")
blame.each do |commit, line| end
data << {
it 'converts to UTF-8' do
expect(CharlockHolmes::EncodingDetector).to receive(:detect).and_return(nil)
data = []
blame.each do |commit, line|
data << {
commit: commit, commit: commit,
line: line line: line
} }
end end
expect(data.size).to eq(1) expect(data.size).to eq(1)
expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit)
expect(data.first[:line]).to eq(" ") expect(data.first[:line]).to eq(" ")
expect(data.first[:line]).to be_utf8 expect(data.first[:line]).to be_utf8
end
end end
end end
context 'when Gitaly blame feature is enabled' do
it_behaves_like 'blaming a file'
end
context 'when Gitaly blame feature is disabled', skip_gitaly_mock: true do
it_behaves_like 'blaming a file'
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment