summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--lib/gitlab/git/operation_service.rb12
-rw-r--r--lib/gitlab/git/repository.rb12
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb31
-rw-r--r--lib/gitlab/gitaly_client/queue_enumerator.rb28
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb39
-rw-r--r--spec/models/repository_spec.rb30
9 files changed, 143 insertions, 17 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 301092317fe..421ab545d9a 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.46.0
+0.47.0
diff --git a/Gemfile b/Gemfile
index c1988aea803..6c9834d7d27 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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
diff --git a/Gemfile.lock b/Gemfile.lock
index 345fc0a9ac0..afb0b6b471d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -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)
diff --git a/lib/gitlab/git/operation_service.rb b/lib/gitlab/git/operation_service.rb
index d835dcca8ba..ab94ba8a73a 100644
--- a/lib/gitlab/git/operation_service.rb
+++ b/lib/gitlab/git/operation_service.rb
@@ -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)
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index a6b2d189f18..f99be3cef7b 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -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|
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 81ddaf13e10..91f34011f6e 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -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
diff --git a/lib/gitlab/gitaly_client/queue_enumerator.rb b/lib/gitlab/gitaly_client/queue_enumerator.rb
new file mode 100644
index 00000000000..b8018029552
--- /dev/null
+++ b/lib/gitlab/gitaly_client/queue_enumerator.rb
@@ -0,0 +1,28 @@
+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
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index b11fa38856b..b2d2f770e3d 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -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
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index f44693a71bb..39d188f18af 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -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)