Commit d7326003 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'gitaly-merge' into 'master'

Merge Merge Requests via Gitaly

Closes gitaly#654

See merge request gitlab-org/gitlab-ce!14791
parents 5e0fca33 0aff29f9
......@@ -398,7 +398,7 @@ group :ed25519 do
end
# 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
......
......@@ -273,7 +273,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
gitaly-proto (0.41.0)
gitaly-proto (0.42.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (4.7.6)
......@@ -1030,7 +1030,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
gitaly-proto (~> 0.41.0)
gitaly-proto (~> 0.42.0)
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.6.2)
......
......@@ -3,9 +3,17 @@ module Gitlab
class OperationService
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 :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
attr_reader :user, :repository
......@@ -112,7 +120,7 @@ module Gitlab
ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name
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
def find_oldrev_from_branch(newrev, branch)
......
......@@ -704,7 +704,17 @@ module Gitlab
tags.find { |tag| tag.name == name }
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)
OperationService.new(user, self).with_branch(target_branch) do |start_commit|
......
......@@ -74,6 +74,37 @@ module Gitlab
raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error
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
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
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)
source_branch = repository.branches.find { |branch| branch.name == source_branch_name }
rugged = repository.rugged
......
......@@ -1286,21 +1286,31 @@ describe Repository do
let(:message) { 'Test \r\n\r\n message' }
it 'merges the code and returns the commit id' do
expect(merge_commit).to be_present
expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present
end
shared_examples '#merge' do
it 'merges the code and returns the commit id' do
expect(merge_commit).to be_present
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
merge_commit_id = merge(repository, user, merge_request, message)
it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do
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
it 'removes carriage returns from commit message' do
merge_commit_id = merge(repository, user, merge_request, message)
context 'with gitaly' do
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
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