Commit 4f5be9ec authored by Ahmad Sherif's avatar Ahmad Sherif

Migrate Gitlab::Git::Repository#add_tag to Gitaly

Closes gitaly#601
parent 07c3112e
...@@ -11,7 +11,7 @@ module Tags ...@@ -11,7 +11,7 @@ module Tags
begin begin
new_tag = repository.add_tag(current_user, tag_name, target, message) new_tag = repository.add_tag(current_user, tag_name, target, message)
rescue Rugged::TagError rescue Gitlab::Git::Repository::TagExistsError
return error("Tag #{tag_name} already exists") return error("Tag #{tag_name} already exists")
rescue Gitlab::Git::HooksService::PreReceiveError => ex rescue Gitlab::Git::HooksService::PreReceiveError => ex
return error(ex.message) return error(ex.message)
......
...@@ -20,6 +20,7 @@ module Gitlab ...@@ -20,6 +20,7 @@ module Gitlab
GitError = Class.new(StandardError) GitError = Class.new(StandardError)
DeleteBranchError = Class.new(StandardError) DeleteBranchError = Class.new(StandardError)
CreateTreeError = Class.new(StandardError) CreateTreeError = Class.new(StandardError)
TagExistsError = Class.new(StandardError)
class << self class << self
# Unlike `new`, `create` takes the storage path, not the storage name # Unlike `new`, `create` takes the storage path, not the storage name
...@@ -646,24 +647,13 @@ module Gitlab ...@@ -646,24 +647,13 @@ module Gitlab
end end
def add_tag(tag_name, user:, target:, message: nil) def add_tag(tag_name, user:, target:, message: nil)
target_object = Ref.dereference_object(lookup(target)) gitaly_migrate(:operation_user_add_tag) do |is_enabled|
raise InvalidRef.new("target not found: #{target}") unless target_object if is_enabled
gitaly_add_tag(tag_name, user: user, target: target, message: message)
user = Gitlab::Git::User.from_gitlab(user) unless user.respond_to?(:gl_id) else
rugged_add_tag(tag_name, user: user, target: target, message: message)
options = nil # Use nil, not the empty hash. Rugged cares about this. end
if message
options = {
message: message,
tagger: Gitlab::Git.committer_hash(email: user.email, name: user.name)
}
end end
OperationService.new(user, self).add_tag(tag_name, target_object.oid, options)
find_tag(tag_name)
rescue Rugged::ReferenceError => ex
raise InvalidRef, ex
end end
def rm_branch(branch_name, user:) def rm_branch(branch_name, user:)
...@@ -1392,6 +1382,33 @@ module Gitlab ...@@ -1392,6 +1382,33 @@ module Gitlab
false false
end end
def gitaly_add_tag(tag_name, user:, target:, message: nil)
gitaly_operations_client.add_tag(tag_name, user, target, message)
end
def rugged_add_tag(tag_name, user:, target:, message: nil)
target_object = Ref.dereference_object(lookup(target))
raise InvalidRef.new("target not found: #{target}") unless target_object
user = Gitlab::Git::User.from_gitlab(user) unless user.respond_to?(:gl_id)
options = nil # Use nil, not the empty hash. Rugged cares about this.
if message
options = {
message: message,
tagger: Gitlab::Git.committer_hash(email: user.email, name: user.name)
}
end
Gitlab::Git::OperationService.new(user, self).add_tag(tag_name, target_object.oid, options)
find_tag(tag_name)
rescue Rugged::ReferenceError => ex
raise InvalidRef, ex
rescue Rugged::TagError
raise TagExistsError
end
def rugged_create_branch(ref, start_point) def rugged_create_branch(ref, start_point)
rugged_ref = rugged.branches.create(ref, start_point) rugged_ref = rugged.branches.create(ref, start_point)
target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target) target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
......
...@@ -19,6 +19,27 @@ module Gitlab ...@@ -19,6 +19,27 @@ module Gitlab
raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error
end end
end end
def add_tag(tag_name, user, target, message)
request = Gitaly::UserCreateTagRequest.new(
repository: @gitaly_repo,
user: Util.gitaly_user(user),
tag_name: GitalyClient.encode(tag_name),
target_revision: GitalyClient.encode(target),
message: GitalyClient.encode(message.to_s)
)
response = GitalyClient.call(@repository.storage, :operation_service, :user_create_tag, request)
if pre_receive_error = response.pre_receive_error.presence
raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error
elsif response.exists
raise Gitlab::Git::Repository::TagExistsError
end
Util.gitlab_tag_from_gitaly_tag(@repository, response.tag)
rescue GRPC::FailedPrecondition => e
raise Gitlab::Git::Repository::InvalidRef, e
end
end end
end end
end end
...@@ -155,19 +155,7 @@ module Gitlab ...@@ -155,19 +155,7 @@ module Gitlab
def consume_tags_response(response) def consume_tags_response(response)
response.flat_map do |message| response.flat_map do |message|
message.tags.map do |gitaly_tag| message.tags.map { |gitaly_tag| Util.gitlab_tag_from_gitaly_tag(@repository, gitaly_tag) }
if gitaly_tag.target_commit.present?
gitaly_commit = Gitlab::Git::Commit.decorate(@repository, gitaly_tag.target_commit)
end
Gitlab::Git::Tag.new(
@repository,
encode!(gitaly_tag.name.dup),
gitaly_tag.id,
gitaly_commit,
encode!(gitaly_tag.message.chomp)
)
end
end end
end end
......
...@@ -20,6 +20,20 @@ module Gitlab ...@@ -20,6 +20,20 @@ module Gitlab
email: GitalyClient.encode(gitlab_user.email) email: GitalyClient.encode(gitlab_user.email)
) )
end end
def gitlab_tag_from_gitaly_tag(repository, gitaly_tag)
if gitaly_tag.target_commit.present?
commit = Gitlab::Git::Commit.decorate(repository, gitaly_tag.target_commit)
end
Gitlab::Git::Tag.new(
repository,
Gitlab::EncodingHelper.encode!(gitaly_tag.name.dup),
gitaly_tag.id,
commit,
Gitlab::EncodingHelper.encode!(gitaly_tag.message.chomp)
)
end
end end
end end
end end
......
...@@ -1617,27 +1617,41 @@ describe Repository do ...@@ -1617,27 +1617,41 @@ describe Repository do
end end
describe '#add_tag' do describe '#add_tag' do
context 'with a valid target' do let(:user) { build_stubbed(:user) }
let(:user) { build_stubbed(:user) }
it 'creates the tag using rugged' do shared_examples 'adding tag' do
expect(repository.rugged.tags).to receive(:create) context 'with a valid target' do
.with('8.5', repository.commit('master').id, it 'creates the tag' do
hash_including(message: 'foo', repository.add_tag(user, '8.5', 'master', 'foo')
tagger: hash_including(name: user.name, email: user.email)))
.and_call_original
repository.add_tag(user, '8.5', 'master', 'foo') tag = repository.find_tag('8.5')
end expect(tag).to be_present
expect(tag.message).to eq('foo')
expect(tag.dereferenced_target.id).to eq(repository.commit('master').id)
end
it 'returns a Gitlab::Git::Tag object' do it 'returns a Gitlab::Git::Tag object' do
tag = repository.add_tag(user, '8.5', 'master', 'foo') tag = repository.add_tag(user, '8.5', 'master', 'foo')
expect(tag).to be_a(Gitlab::Git::Tag)
end
end
expect(tag).to be_a(Gitlab::Git::Tag) context 'with an invalid target' do
it 'returns false' do
expect(repository.add_tag(user, '8.5', 'bar', 'foo')).to be false
end
end end
end
it 'passes commit SHA to pre-receive and update hooks,\ context 'when Gitaly operation_user_add_tag feature is enabled' do
and tag SHA to post-receive hook' do it_behaves_like 'adding tag'
end
context 'when Gitaly operation_user_add_tag feature is disabled', skip_gitaly_mock: true do
it_behaves_like 'adding tag'
it 'passes commit SHA to pre-receive and update hooks and tag SHA to post-receive hook' do
pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', project) pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', project)
update_hook = Gitlab::Git::Hook.new('update', project) update_hook = Gitlab::Git::Hook.new('update', project)
post_receive_hook = Gitlab::Git::Hook.new('post-receive', project) post_receive_hook = Gitlab::Git::Hook.new('post-receive', project)
...@@ -1662,12 +1676,6 @@ describe Repository do ...@@ -1662,12 +1676,6 @@ describe Repository do
.with(anything, anything, tag_sha, anything) .with(anything, anything, tag_sha, anything)
end end
end end
context 'with an invalid target' do
it 'returns false' do
expect(repository.add_tag(user, '8.5', 'bar', 'foo')).to be false
end
end
end end
describe '#rm_branch' do describe '#rm_branch' do
......
...@@ -28,7 +28,7 @@ describe Tags::CreateService do ...@@ -28,7 +28,7 @@ describe Tags::CreateService do
it 'returns an error' do it 'returns an error' do
expect(repository).to receive(:add_tag) expect(repository).to receive(:add_tag)
.with(user, 'v1.1.0', 'master', 'Foo') .with(user, 'v1.1.0', 'master', 'Foo')
.and_raise(Rugged::TagError) .and_raise(Gitlab::Git::Repository::TagExistsError)
response = service.execute('v1.1.0', 'master', 'Foo') response = service.execute('v1.1.0', 'master', 'Foo')
......
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