Commit 0a47d192 authored by Zeger-Jan van de Weg's avatar Zeger-Jan van de Weg

Client changes for Tag,BranchNamesContainingCommit

As part of gitlab-org/gitaly#884, this commit contains the client
implementation for both TagNamesContaintingCommit and
BranchNamesContainingCommit. The interface in the Repository model stays
the same, but the implementation on the serverside, e.g. Gitaly, uses
`for-each-ref`, as opposed to `branch` or `tag` which both aren't
plumbing command. The result stays the same.

On the serverside, we have the opportunity to limit the number of names
to return. However, this is not supported on the front end yet. My
proposal to use this ability: gitlab-org/gitlab-ce#42581. For now, this
ability is not used as that would change more behaviours on a feature
flag which might lead to unexpected changes on page refresh for example.
parent 498d3236
...@@ -721,11 +721,11 @@ class Repository ...@@ -721,11 +721,11 @@ class Repository
end end
def branch_names_contains(sha) def branch_names_contains(sha)
refs_contains_sha('branch', sha) raw_repository.branch_names_contains_sha(sha)
end end
def tag_names_contains(sha) def tag_names_contains(sha)
refs_contains_sha('tag', sha) raw_repository.tag_names_contains_sha(sha)
end end
def local_branches def local_branches
......
# Gitaly note: JV: no RPC's here.
module Gitlab module Gitlab
module Git module Git
class Branch < Ref class Branch < Ref
def self.find(repo, branch_name) class << self
if branch_name.is_a?(Gitlab::Git::Branch) def find(repo, branch_name)
branch_name if branch_name.is_a?(Gitlab::Git::Branch)
else branch_name
repo.find_branch(branch_name) else
repo.find_branch(branch_name)
end
end
def names_contains_sha(repo, sha, limit: 0)
GitalyClient::RefService.new(repo).branch_names_contains_sha(sha)
end end
end end
......
...@@ -1355,20 +1355,23 @@ module Gitlab ...@@ -1355,20 +1355,23 @@ module Gitlab
raise CommandError.new(e) raise CommandError.new(e)
end end
def refs_contains_sha(ref_type, sha) def branch_names_contains_sha(sha)
args = %W(#{ref_type} --contains #{sha}) gitaly_migrate(:branch_names_contains_sha) do |is_enabled|
names = run_git(args).first if is_enabled
Gitlab::Git::Branch.names_contains_sha(self, sha)
if names.respond_to?(:split) else
names = names.split("\n").map(&:strip) refs_contains_sha(:branch, sha)
names.each do |name|
name.slice! '* '
end end
end
end
names def tag_names_contains_sha(sha)
else gitaly_migrate(:tag_names_contains_sha) do |is_enabled|
[] if is_enabled
Gitlab::Git::Tag.names_contains_sha(self, sha)
else
refs_contains_sha(:tag, sha)
end
end end
end end
...@@ -1446,6 +1449,21 @@ module Gitlab ...@@ -1446,6 +1449,21 @@ module Gitlab
end end
end end
def refs_contains_sha(ref_type, sha)
args = %W(#{ref_type} --contains #{sha})
names = run_git(args).first
return [] unless names.respond_to?(:split)
names = names.split("\n").map(&:strip)
names.each do |name|
name.slice! '* '
end
names
end
def shell_write_ref(ref_path, ref, old_ref) def shell_write_ref(ref_path, ref, old_ref)
raise ArgumentError, "invalid ref_path #{ref_path.inspect}" if ref_path.include?(' ') raise ArgumentError, "invalid ref_path #{ref_path.inspect}" if ref_path.include?(' ')
raise ArgumentError, "invalid ref #{ref.inspect}" if ref.include?("\x00") raise ArgumentError, "invalid ref #{ref.inspect}" if ref.include?("\x00")
......
# Gitaly note: JV: no RPC's here.
#
module Gitlab module Gitlab
module Git module Git
class Tag < Ref class Tag < Ref
class << self
def names_contains_sha(repo, sha)
GitalyClient::RefService.new(repo).branch_names_contains_sha(sha)
end
end
attr_reader :object_sha attr_reader :object_sha
def initialize(repository, name, target, target_commit, message = nil) def initialize(repository, name, target, target_commit, message = nil)
......
...@@ -145,6 +145,32 @@ module Gitlab ...@@ -145,6 +145,32 @@ module Gitlab
raise Gitlab::Git::Repository::GitError, response.git_error if response.git_error.present? raise Gitlab::Git::Repository::GitError, response.git_error if response.git_error.present?
end end
# Limit: 0 implies no limit, thus all tag names will be returned
def tag_names_containing(sha, limit: 0)
request = Gitaly::ListTagNamesContainingCommitRequest.new(
repository: @gitaly_repo,
commit_id: sha,
limit: limit
)
stream = GitalyClient.call(@repository.storage, :ref_service, :list_tag_names_containing_commit, request)
stream.each_with_object([]) { |response, array| array.concat(response.tag_names) }
end
# Limit: 0 implies no limit, thus all tag names will be returned
def branch_names_contains_sha(sha, limit: 0)
request = Gitaly::ListBranchNamesContainingCommitRequest.new(
repository: @gitaly_repo,
commit_id: sha,
limit: limit
)
stream = GitalyClient.call(@repository.storage, :ref_service, :list_branch_names_containing_commit, request)
stream.each_with_object([]) { |response, array| array.concat(response.branch_names) }
end
private private
def consume_refs_response(response) def consume_refs_response(response)
......
...@@ -36,26 +36,49 @@ describe Repository do ...@@ -36,26 +36,49 @@ describe Repository do
end end
describe '#branch_names_contains' do describe '#branch_names_contains' do
subject { repository.branch_names_contains(sample_commit.id) } shared_examples '#branch_names_contains' do
set(:project) { create(:project, :repository) }
let(:repository) { project.repository }
it { is_expected.to include('master') } subject { repository.branch_names_contains(sample_commit.id) }
it { is_expected.not_to include('feature') }
it { is_expected.not_to include('fix') }
describe 'when storage is broken', :broken_storage do it { is_expected.to include('master') }
it 'should raise a storage error' do it { is_expected.not_to include('feature') }
expect_to_raise_storage_error do it { is_expected.not_to include('fix') }
broken_repository.branch_names_contains(sample_commit.id)
describe 'when storage is broken', :broken_storage do
it 'should raise a storage error' do
expect_to_raise_storage_error do
broken_repository.branch_names_contains(sample_commit.id)
end
end end
end end
end end
context 'when gitaly is enabled' do
it_behaves_like '#branch_names_contains'
end
context 'when gitaly is disabled', :skip_gitaly_mock do
it_behaves_like '#branch_names_contains'
end
end end
describe '#tag_names_contains' do describe '#tag_names_contains' do
subject { repository.tag_names_contains(sample_commit.id) } shared_examples '#tag_names_contains' do
subject { repository.tag_names_contains(sample_commit.id) }
it { is_expected.to include('v1.1.0') }
it { is_expected.not_to include('v1.0.0') }
end
context 'when gitaly is enabled' do
it_behaves_like '#tag_names_contains'
end
it { is_expected.to include('v1.1.0') } context 'when gitaly is enabled', :skip_gitaly_mock do
it { is_expected.not_to include('v1.0.0') } it_behaves_like '#tag_names_contains'
end
end end
describe 'tags_sorted_by' do describe 'tags_sorted_by' do
......
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