Commit aaa887fe authored by Andrew Newdigate's avatar Andrew Newdigate

Client Implementation: RefService::RefExists

parent 6ed01ebf
...@@ -401,7 +401,7 @@ group :ed25519 do ...@@ -401,7 +401,7 @@ group :ed25519 do
end end
# Gitaly GRPC client # Gitaly GRPC client
gem 'gitaly', '~> 0.27.0' gem 'gitaly', '~> 0.29.0'
gem 'toml-rb', '~> 0.3.15', require: false gem 'toml-rb', '~> 0.3.15', require: false
......
...@@ -275,7 +275,7 @@ GEM ...@@ -275,7 +275,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.27.0) gitaly (0.29.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)
...@@ -1019,7 +1019,7 @@ DEPENDENCIES ...@@ -1019,7 +1019,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.27.0) gitaly (~> 0.29.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)
......
---
title: Implement the Gitaly RefService::RefExists endpoint
merge_request: 13528
author: Andrew Newdigate
...@@ -204,21 +204,26 @@ module Gitlab ...@@ -204,21 +204,26 @@ module Gitlab
# #
# name - The name of the tag as a String. # name - The name of the tag as a String.
def tag_exists?(name) def tag_exists?(name)
!!rugged.tags[name] gitaly_migrate(:ref_exists_tags) do |is_enabled|
if is_enabled
gitaly_ref_exists?("refs/tags/#{name}")
else
rugged_tag_exists?(name)
end
end
end end
# Returns true if the given branch exists # Returns true if the given branch exists
# #
# name - The name of the branch as a String. # name - The name of the branch as a String.
def branch_exists?(name) def branch_exists?(name)
rugged.branches.exists?(name) gitaly_migrate(:ref_exists_branches) do |is_enabled|
if is_enabled
# If the branch name is invalid (e.g. ".foo") Rugged will raise an error. gitaly_ref_exists?("refs/heads/#{name}")
# Whatever code calls this method shouldn't have to deal with that so else
# instead we just return `false` (which is true since a branch doesn't rugged_branch_exists?(name)
# exist when it has an invalid name). end
rescue Rugged::ReferenceError end
false
end end
# Returns an Array of branch and tag names # Returns an Array of branch and tag names
...@@ -995,6 +1000,34 @@ module Gitlab ...@@ -995,6 +1000,34 @@ module Gitlab
raw_output.compact raw_output.compact
end end
# Returns true if the given ref name exists
#
# Ref names must start with `refs/`.
def gitaly_ref_exists?(ref_name)
gitaly_ref_client.ref_exists?(ref_name)
end
# Returns true if the given tag exists
#
# name - The name of the tag as a String.
def rugged_tag_exists?(name)
!!rugged.tags[name]
end
# Returns true if the given branch exists
#
# name - The name of the branch as a String.
def rugged_branch_exists?(name)
rugged.branches.exists?(name)
# If the branch name is invalid (e.g. ".foo") Rugged will raise an error.
# Whatever code calls this method shouldn't have to deal with that so
# instead we just return `false` (which is true since a branch doesn't
# exist when it has an invalid name).
rescue Rugged::ReferenceError
false
end
def gitaly_copy_gitattributes(revision) def gitaly_copy_gitattributes(revision)
gitaly_repository_client.apply_gitattributes(revision) gitaly_repository_client.apply_gitattributes(revision)
end end
......
...@@ -70,6 +70,14 @@ module Gitlab ...@@ -70,6 +70,14 @@ module Gitlab
consume_tags_response(response) consume_tags_response(response)
end end
def ref_exists?(ref_name)
request = Gitaly::RefExistsRequest.new(repository: @gitaly_repo, ref: ref_name)
response = GitalyClient.call(@storage, :ref_service, :ref_exists, request)
response.value
rescue GRPC::InvalidArgument => e
raise ArgumentError, e.message
end
private private
def consume_refs_response(response) def consume_refs_response(response)
......
...@@ -1098,6 +1098,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1098,6 +1098,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
describe '#tag_exists?' do describe '#tag_exists?' do
shared_examples 'checks the existence of tags' do
it 'returns true for an existing tag' do it 'returns true for an existing tag' do
tag = repository.tag_names.first tag = repository.tag_names.first
...@@ -1109,7 +1110,17 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1109,7 +1110,17 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
context 'when Gitaly ref_exists_tags feature is enabled' do
it_behaves_like 'checks the existence of tags'
end
context 'when Gitaly ref_exists_tags feature is disabled', skip_gitaly_mock: true do
it_behaves_like 'checks the existence of tags'
end
end
describe '#branch_exists?' do describe '#branch_exists?' do
shared_examples 'checks the existence of branches' do
it 'returns true for an existing branch' do it 'returns true for an existing branch' do
expect(repository.branch_exists?('master')).to eq(true) expect(repository.branch_exists?('master')).to eq(true)
end end
...@@ -1123,6 +1134,15 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1123,6 +1134,15 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
context 'when Gitaly ref_exists_branches feature is enabled' do
it_behaves_like 'checks the existence of branches'
end
context 'when Gitaly ref_exists_branches feature is disabled', skip_gitaly_mock: true do
it_behaves_like 'checks the existence of branches'
end
end
describe '#local_branches' do describe '#local_branches' do
before(:all) do before(:all) do
@repo = Gitlab::Git::Repository.new('default', File.join(TEST_MUTABLE_REPO_PATH, '.git')) @repo = Gitlab::Git::Repository.new('default', File.join(TEST_MUTABLE_REPO_PATH, '.git'))
......
require 'spec_helper' require 'spec_helper'
describe Gitlab::GitalyClient::RefService do describe Gitlab::GitalyClient::RefService do
let(:project) { create(:project) } let(:project) { create(:project, :repository) }
let(:storage_name) { project.repository_storage } let(:storage_name) { project.repository_storage }
let(:relative_path) { project.disk_path + '.git' } let(:relative_path) { project.disk_path + '.git' }
let(:client) { described_class.new(project.repository) } let(:repository) { project.repository }
let(:client) { described_class.new(repository) }
describe '#branches' do describe '#branches' do
it 'sends a find_all_branches message' do it 'sends a find_all_branches message' do
...@@ -84,11 +85,23 @@ describe Gitlab::GitalyClient::RefService do ...@@ -84,11 +85,23 @@ describe Gitlab::GitalyClient::RefService do
end end
describe '#find_ref_name', seed_helper: true do describe '#find_ref_name', seed_helper: true do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
let(:client) { described_class.new(repository) }
subject { client.find_ref_name(SeedRepo::Commit::ID, 'refs/heads/master') } subject { client.find_ref_name(SeedRepo::Commit::ID, 'refs/heads/master') }
it { is_expected.to be_utf8 } it { is_expected.to be_utf8 }
it { is_expected.to eq('refs/heads/master') } it { is_expected.to eq('refs/heads/master') }
end end
describe '#ref_exists?', seed_helper: true do
it 'finds the master branch ref' do
expect(client.ref_exists?('refs/heads/master')).to eq(true)
end
it 'returns false for an illegal tag name ref' do
expect(client.ref_exists?('refs/tags/.this-tag-name-is-illegal')).to eq(false)
end
it 'raises an argument error if the ref name parameter does not start with refs/' do
expect { client.ref_exists?('reXXXXX') }.to raise_error(ArgumentError)
end
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