Commit 0aff29f9 authored by Jacob Vosmaer's avatar Jacob Vosmaer

Merge Merge Requests via Gitaly

parent c08fea6f
...@@ -398,7 +398,7 @@ group :ed25519 do ...@@ -398,7 +398,7 @@ group :ed25519 do
end end
# Gitaly GRPC client # Gitaly GRPC client
gem 'gitaly-proto', '~> 0.41.0', require: 'gitaly' gem 'gitaly-proto', '~> 0.42.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false gem 'toml-rb', '~> 0.3.15', require: false
......
...@@ -273,7 +273,7 @@ GEM ...@@ -273,7 +273,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-proto (0.41.0) gitaly-proto (0.42.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)
...@@ -1027,7 +1027,7 @@ DEPENDENCIES ...@@ -1027,7 +1027,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-proto (~> 0.41.0) gitaly-proto (~> 0.42.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.6.2) gitlab-markup (~> 1.6.2)
......
...@@ -3,9 +3,17 @@ module Gitlab ...@@ -3,9 +3,17 @@ module Gitlab
class OperationService class OperationService
include Gitlab::Git::Popen include Gitlab::Git::Popen
WithBranchResult = Struct.new(:newrev, :repo_created, :branch_created) do BranchUpdate = Struct.new(:newrev, :repo_created, :branch_created) do
alias_method :repo_created?, :repo_created alias_method :repo_created?, :repo_created
alias_method :branch_created?, :branch_created alias_method :branch_created?, :branch_created
def self.from_gitaly(branch_update)
new(
branch_update.commit_id,
branch_update.repo_created,
branch_update.branch_created
)
end
end end
attr_reader :user, :repository attr_reader :user, :repository
...@@ -112,7 +120,7 @@ module Gitlab ...@@ -112,7 +120,7 @@ module Gitlab
ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name
update_ref_in_hooks(ref, newrev, oldrev) update_ref_in_hooks(ref, newrev, oldrev)
WithBranchResult.new(newrev, was_empty, was_empty || Gitlab::Git.blank_ref?(oldrev)) BranchUpdate.new(newrev, was_empty, was_empty || Gitlab::Git.blank_ref?(oldrev))
end end
def find_oldrev_from_branch(newrev, branch) def find_oldrev_from_branch(newrev, branch)
......
...@@ -704,7 +704,17 @@ module Gitlab ...@@ -704,7 +704,17 @@ module Gitlab
tags.find { |tag| tag.name == name } tags.find { |tag| tag.name == name }
end end
def merge(user, source_sha, target_branch, message) def merge(user, source_sha, target_branch, message, &block)
gitaly_migrate(:operation_user_merge_branch) do |is_enabled|
if is_enabled
gitaly_operation_client.user_merge_branch(user, source_sha, target_branch, message, &block)
else
rugged_merge(user, source_sha, target_branch, message, &block)
end
end
end
def rugged_merge(user, source_sha, target_branch, message)
committer = Gitlab::Git.committer_hash(email: user.email, name: user.name) committer = Gitlab::Git.committer_hash(email: user.email, name: user.name)
OperationService.new(user, self).with_branch(target_branch) do |start_commit| OperationService.new(user, self).with_branch(target_branch) do |start_commit|
......
...@@ -74,6 +74,37 @@ module Gitlab ...@@ -74,6 +74,37 @@ module Gitlab
raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error
end end
end end
def user_merge_branch(user, source_sha, target_branch, message)
request_enum = QueueEnumerator.new
response_enum = GitalyClient.call(
@repository.storage,
:operation_service,
:user_merge_branch,
request_enum.each
)
request_enum.push(
Gitaly::UserMergeBranchRequest.new(
repository: @gitaly_repo,
user: Util.gitaly_user(user),
commit_id: source_sha,
branch: GitalyClient.encode(target_branch),
message: GitalyClient.encode(message)
)
)
yield response_enum.next.commit_id
request_enum.push(Gitaly::UserMergeBranchRequest.new(apply: true))
branch_update = response_enum.next.branch_update
raise Gitlab::Git::CommitError.new('failed to apply merge to branch') unless branch_update.commit_id.present?
Gitlab::Git::OperationService::BranchUpdate.from_gitaly(branch_update)
ensure
request_enum.close
end
end end
end end
end end
module Gitlab
module GitalyClient
class QueueEnumerator
def initialize
@queue = Queue.new
end
def push(elem)
@queue << elem
end
def close
push(:close)
end
def each
return enum_for(:each) unless block_given?
loop do
elem = @queue.pop
break if elem == :close
yield elem
end
end
end
end
end
...@@ -1525,6 +1525,45 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1525,6 +1525,45 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
describe '#merge' do
let(:repository) do
Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
end
let(:source_sha) { '913c66a37b4a45b9769037c55c2d238bd0942d2e' }
let(:user) { build(:user) }
let(:target_branch) { 'test-merge-target-branch' }
before do
repository.create_branch(target_branch, '6d394385cf567f80a8fd85055db1ab4c5295806f')
end
after do
FileUtils.rm_rf(TEST_MUTABLE_REPO_PATH)
ensure_seeds
end
shared_examples '#merge' do
it 'can perform a merge' do
merge_commit_id = nil
result = repository.merge(user, source_sha, target_branch, 'Test merge') do |commit_id|
merge_commit_id = commit_id
end
expect(result.newrev).to eq(merge_commit_id)
expect(result.repo_created).to eq(false)
expect(result.branch_created).to eq(false)
end
end
context 'with gitaly' do
it_behaves_like '#merge'
end
context 'without gitaly', :skip_gitaly_mock do
it_behaves_like '#merge'
end
end
def create_remote_branch(repository, remote_name, branch_name, source_branch_name) def create_remote_branch(repository, remote_name, branch_name, source_branch_name)
source_branch = repository.branches.find { |branch| branch.name == source_branch_name } source_branch = repository.branches.find { |branch| branch.name == source_branch_name }
rugged = repository.rugged rugged = repository.rugged
......
...@@ -1286,21 +1286,31 @@ describe Repository do ...@@ -1286,21 +1286,31 @@ describe Repository do
let(:message) { 'Test \r\n\r\n message' } let(:message) { 'Test \r\n\r\n message' }
it 'merges the code and returns the commit id' do shared_examples '#merge' do
expect(merge_commit).to be_present it 'merges the code and returns the commit id' do
expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present expect(merge_commit).to be_present
end expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present
end
it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do
merge_commit_id = merge(repository, user, merge_request, message) merge_commit_id = merge(repository, user, merge_request, message)
expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id) expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id)
end
it 'removes carriage returns from commit message' do
merge_commit_id = merge(repository, user, merge_request, message)
expect(repository.commit(merge_commit_id).message).to eq(message.delete("\r"))
end
end end
it 'removes carriage returns from commit message' do context 'with gitaly' do
merge_commit_id = merge(repository, user, merge_request, message) it_behaves_like '#merge'
end
expect(repository.commit(merge_commit_id).message).to eq(message.delete("\r")) context 'without gitaly', :skip_gitaly_mock do
it_behaves_like '#merge'
end end
def merge(repository, user, merge_request, message) def merge(repository, user, merge_request, message)
......
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