diff options
Diffstat (limited to 'spec/lib/gitlab/git')
-rw-r--r-- | spec/lib/gitlab/git/commit_spec.rb | 36 | ||||
-rw-r--r-- | spec/lib/gitlab/git/repository_spec.rb | 288 | ||||
-rw-r--r-- | spec/lib/gitlab/git/tag_spec.rb | 14 | ||||
-rw-r--r-- | spec/lib/gitlab/git/tree_spec.rb | 107 |
4 files changed, 333 insertions, 112 deletions
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb index f58bab52cfa..f4dba5e8d58 100644 --- a/spec/lib/gitlab/git/commit_spec.rb +++ b/spec/lib/gitlab/git/commit_spec.rb @@ -364,19 +364,39 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do end describe '.between' do - subject do - commits = described_class.between(repository, SeedRepo::Commit::PARENT_ID, SeedRepo::Commit::ID) - commits.map { |c| c.id } + let(:limit) { nil } + let(:commit_ids) { commits.map(&:id) } + + subject(:commits) { described_class.between(repository, from, to, limit: limit) } + + context 'requesting a single commit' do + let(:from) { SeedRepo::Commit::PARENT_ID } + let(:to) { SeedRepo::Commit::ID } + + it { expect(commit_ids).to contain_exactly(to) } end - it { is_expected.to contain_exactly(SeedRepo::Commit::ID) } + context 'requesting a commit range' do + let(:from) { 'v1.0.0' } + let(:to) { 'v1.2.0' } - context 'between_uses_list_commits FF disabled' do - before do - stub_feature_flags(between_uses_list_commits: false) + let(:commits_in_range) do + %w[ + 570e7b2abdd848b95f2f578043fc23bd6f6fd24d + 5937ac0a7beb003549fc5fd26fc247adbce4a52e + eb49186cfa5c4338011f5f590fac11bd66c5c631 + ] end - it { is_expected.to contain_exactly(SeedRepo::Commit::ID) } + context 'no limit' do + it { expect(commit_ids).to eq(commits_in_range) } + end + + context 'limited' do + let(:limit) { 2 } + + it { expect(commit_ids).to eq(commits_in_range.last(2)) } + end end end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 29e7a1dce1d..9ecd281cce0 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -109,6 +109,32 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RefService, :tag_names end + describe '#tags' do + subject { repository.tags } + + it 'gets tags from GitalyClient' do + expect_next_instance_of(Gitlab::GitalyClient::RefService) do |service| + expect(service).to receive(:tags) + end + + subject + end + + context 'with sorting option' do + subject { repository.tags(sort_by: 'name_asc') } + + it 'gets tags from GitalyClient' do + expect_next_instance_of(Gitlab::GitalyClient::RefService) do |service| + expect(service).to receive(:tags).with(sort_by: 'name_asc') + end + + subject + end + end + + it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RefService, :tags + end + describe '#archive_metadata' do let(:storage_path) { '/tmp' } let(:cache_key) { File.join(repository.gl_repository, SeedRepo::LastCommit::ID) } @@ -936,6 +962,159 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do end end + describe '#new_blobs' do + let(:repository) { mutable_repository } + let(:repository_rugged) { mutable_repository_rugged } + let(:blob) { create_blob('This is a new blob') } + let(:commit) { create_commit('nested/new-blob.txt' => blob) } + + def create_blob(content) + repository_rugged.write(content, :blob) + end + + def create_commit(blobs) + author = { name: 'Test User', email: 'mail@example.com', time: Time.now } + + index = repository_rugged.index + blobs.each do |path, oid| + index.add(path: path, oid: oid, mode: 0100644) + end + + Rugged::Commit.create(repository_rugged, + author: author, + committer: author, + message: "Message", + parents: [], + tree: index.write_tree(repository_rugged)) + end + + subject { repository.new_blobs(newrevs).to_a } + + shared_examples '#new_blobs with revisions' do + before do + expect_next_instance_of(Gitlab::GitalyClient::BlobService) do |service| + expect(service) + .to receive(:list_blobs) + .with(expected_newrevs, + limit: Gitlab::Git::Repository::REV_LIST_COMMIT_LIMIT, + with_paths: true, + dynamic_timeout: nil) + .once + .and_call_original + end + end + + it 'enumerates new blobs' do + expect(subject).to match_array(expected_blobs) + end + + it 'memoizes results' do + expect(subject).to match_array(expected_blobs) + expect(subject).to match_array(expected_blobs) + end + end + + context 'with a single revision' do + let(:newrevs) { commit } + let(:expected_newrevs) { ['--not', '--all', '--not', newrevs] } + let(:expected_blobs) do + [have_attributes(class: Gitlab::Git::Blob, id: blob, path: 'nested/new-blob.txt', size: 18)] + end + + it_behaves_like '#new_blobs with revisions' + end + + context 'with a single-entry array' do + let(:newrevs) { [commit] } + let(:expected_newrevs) { ['--not', '--all', '--not'] + newrevs } + let(:expected_blobs) do + [have_attributes(class: Gitlab::Git::Blob, id: blob, path: 'nested/new-blob.txt', size: 18)] + end + + it_behaves_like '#new_blobs with revisions' + end + + context 'with multiple revisions' do + let(:another_blob) { create_blob('Another blob') } + let(:newrevs) { [commit, create_commit('another_path.txt' => another_blob)] } + let(:expected_newrevs) { ['--not', '--all', '--not'] + newrevs.sort } + let(:expected_blobs) do + [ + have_attributes(class: Gitlab::Git::Blob, id: blob, path: 'nested/new-blob.txt', size: 18), + have_attributes(class: Gitlab::Git::Blob, id: another_blob, path: 'another_path.txt', size: 12) + ] + end + + it_behaves_like '#new_blobs with revisions' + end + + context 'with partially blank revisions' do + let(:newrevs) { [nil, commit, Gitlab::Git::BLANK_SHA] } + let(:expected_newrevs) { ['--not', '--all', '--not', commit] } + let(:expected_blobs) do + [ + have_attributes(class: Gitlab::Git::Blob, id: blob, path: 'nested/new-blob.txt', size: 18) + ] + end + + it_behaves_like '#new_blobs with revisions' + end + + context 'with repeated revisions' do + let(:newrevs) { [commit, commit, commit] } + let(:expected_newrevs) { ['--not', '--all', '--not', commit] } + let(:expected_blobs) do + [ + have_attributes(class: Gitlab::Git::Blob, id: blob, path: 'nested/new-blob.txt', size: 18) + ] + end + + it_behaves_like '#new_blobs with revisions' + end + + context 'with preexisting commits' do + let(:newrevs) { ['refs/heads/master'] } + let(:expected_newrevs) { ['--not', '--all', '--not'] + newrevs } + let(:expected_blobs) { [] } + + it_behaves_like '#new_blobs with revisions' + end + + shared_examples '#new_blobs without revisions' do + before do + expect(Gitlab::GitalyClient::BlobService).not_to receive(:new) + end + + it 'returns an empty array' do + expect(subject).to eq([]) + end + end + + context 'with a single nil newrev' do + let(:newrevs) { nil } + + it_behaves_like '#new_blobs without revisions' + end + + context 'with a single zero newrev' do + let(:newrevs) { Gitlab::Git::BLANK_SHA } + + it_behaves_like '#new_blobs without revisions' + end + + context 'with an empty array' do + let(:newrevs) { [] } + + it_behaves_like '#new_blobs without revisions' + end + + context 'with array containing only empty refs' do + let(:newrevs) { [nil, Gitlab::Git::BLANK_SHA] } + + it_behaves_like '#new_blobs without revisions' + end + end + describe '#new_commits' do let(:repository) { mutable_repository } let(:new_commit) do @@ -1132,28 +1311,6 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do end end - describe '#ref_name_for_sha' do - let(:ref_path) { 'refs/heads' } - let(:sha) { repository.find_branch('master').dereferenced_target.id } - let(:ref_name) { 'refs/heads/master' } - - it 'returns the ref name for the given sha' do - expect(repository.ref_name_for_sha(ref_path, sha)).to eq(ref_name) - end - - it "returns an empty name if the ref doesn't exist" do - expect(repository.ref_name_for_sha(ref_path, "000000")).to eq("") - end - - it "raise an exception if the ref is empty" do - expect { repository.ref_name_for_sha(ref_path, "") }.to raise_error(ArgumentError) - end - - it "raise an exception if the ref is nil" do - expect { repository.ref_name_for_sha(ref_path, nil) }.to raise_error(ArgumentError) - end - end - describe '#branches' do subject { repository.branches } @@ -1732,83 +1889,42 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do end describe '#set_full_path' do - shared_examples '#set_full_path' do - before do - repository_rugged.config["gitlab.fullpath"] = repository_path - end - - context 'is given a path' do - it 'writes it to disk' do - repository.set_full_path(full_path: "not-the/real-path.git") - - config = File.read(File.join(repository_path, "config")) - - expect(config).to include("[gitlab]") - expect(config).to include("fullpath = not-the/real-path.git") - end - end - - context 'it is given an empty path' do - it 'does not write it to disk' do - repository.set_full_path(full_path: "") - - config = File.read(File.join(repository_path, "config")) - - expect(config).to include("[gitlab]") - expect(config).to include("fullpath = #{repository_path}") - end - end + before do + repository_rugged.config["gitlab.fullpath"] = repository_path + end - context 'repository does not exist' do - it 'raises NoRepository and does not call Gitaly WriteConfig' do - repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '', 'group/project') + context 'is given a path' do + it 'writes it to disk' do + repository.set_full_path(full_path: "not-the/real-path.git") - expect(repository.gitaly_repository_client).not_to receive(:set_full_path) + config = File.read(File.join(repository_path, "config")) - expect do - repository.set_full_path(full_path: 'foo/bar.git') - end.to raise_error(Gitlab::Git::Repository::NoRepository) - end + expect(config).to include("[gitlab]") + expect(config).to include("fullpath = not-the/real-path.git") end end - context 'with :set_full_path enabled' do - before do - stub_feature_flags(set_full_path: true) - end + context 'it is given an empty path' do + it 'does not write it to disk' do + repository.set_full_path(full_path: "") - it_behaves_like '#set_full_path' - end + config = File.read(File.join(repository_path, "config")) - context 'with :set_full_path disabled' do - before do - stub_feature_flags(set_full_path: false) + expect(config).to include("[gitlab]") + expect(config).to include("fullpath = #{repository_path}") end - - it_behaves_like '#set_full_path' end - end - describe '#set_config' do - let(:repository) { mutable_repository } - let(:entries) do - { - 'test.foo1' => 'bla bla', - 'test.foo2' => 1234, - 'test.foo3' => true - } - end + context 'repository does not exist' do + it 'raises NoRepository and does not call Gitaly WriteConfig' do + repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '', 'group/project') - it 'can set config settings' do - expect(repository.set_config(entries)).to be_nil + expect(repository.gitaly_repository_client).not_to receive(:set_full_path) - expect(repository_rugged.config['test.foo1']).to eq('bla bla') - expect(repository_rugged.config['test.foo2']).to eq('1234') - expect(repository_rugged.config['test.foo3']).to eq('true') - end - - after do - entries.keys.each { |k| repository_rugged.config.delete(k) } + expect do + repository.set_full_path(full_path: 'foo/bar.git') + end.to raise_error(Gitlab::Git::Repository::NoRepository) + end end end diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb index 79ae47f8a7b..4f56595d7d2 100644 --- a/spec/lib/gitlab/git/tag_spec.rb +++ b/spec/lib/gitlab/git/tag_spec.rb @@ -38,7 +38,7 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do it { expect(tag.tagger.timezone).to eq("+0200") } end - shared_examples 'signed tag' do + describe 'signed tag' do let(:project) { create(:project, :repository) } let(:tag) { project.repository.find_tag('v1.1.1') } @@ -54,18 +54,6 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do it { expect(tag.tagger.timezone).to eq("+0100") } end - context 'with :get_tag_signatures enabled' do - it_behaves_like 'signed tag' - end - - context 'with :get_tag_signatures disabled' do - before do - stub_feature_flags(get_tag_signatures: false) - end - - it_behaves_like 'signed tag' - end - it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) } end diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb index f11d84bd8d3..005f8ecaa3a 100644 --- a/spec/lib/gitlab/git/tree_spec.rb +++ b/spec/lib/gitlab/git/tree_spec.rb @@ -189,12 +189,109 @@ RSpec.describe Gitlab::Git::Tree, :seed_helper do end it_behaves_like :repo do - context 'with pagination parameters' do - let(:pagination_params) { { limit: 3, page_token: nil } } + describe 'Pagination' do + context 'with restrictive limit' do + let(:pagination_params) { { limit: 3, page_token: nil } } + + it 'returns limited paginated list of tree objects' do + expect(entries.count).to eq(3) + expect(cursor.next_cursor).to be_present + end + end + + context 'when limit is equal to number of entries' do + let(:entries_count) { entries.count } + + it 'returns all entries without a cursor' do + result, cursor = Gitlab::Git::Tree.where(repository, sha, path, recursive, { limit: entries_count, page_token: nil }) + + expect(cursor).to be_nil + expect(result.entries.count).to eq(entries_count) + end + end + + context 'when limit is 0' do + let(:pagination_params) { { limit: 0, page_token: nil } } + + it 'returns empty result' do + expect(entries).to eq([]) + expect(cursor).to be_nil + end + end + + context 'when limit is missing' do + let(:pagination_params) { { limit: nil, page_token: nil } } + + it 'returns empty result' do + expect(entries).to eq([]) + expect(cursor).to be_nil + end + end + + context 'when limit is negative' do + let(:entries_count) { entries.count } + + it 'returns all entries' do + result, cursor = Gitlab::Git::Tree.where(repository, sha, path, recursive, { limit: -1, page_token: nil }) + + expect(result.count).to eq(entries_count) + expect(cursor).to be_nil + end + + context 'when token is provided' do + let(:pagination_params) { { limit: 1000, page_token: nil } } + let(:token) { entries.second.id } + + it 'returns all entries after token' do + result, cursor = Gitlab::Git::Tree.where(repository, sha, path, recursive, { limit: -1, page_token: token }) + + expect(result.count).to eq(entries.count - 2) + expect(cursor).to be_nil + end + end + end + + context 'when token does not exist' do + let(:pagination_params) { { limit: 5, page_token: 'aabbccdd' } } + + it 'raises a command error' do + expect { entries }.to raise_error(Gitlab::Git::CommandError, 'could not find starting OID: aabbccdd') + end + end + + context 'when limit is bigger than number of entries' do + let(:pagination_params) { { limit: 1000, page_token: nil } } + + it 'returns only available entries' do + expect(entries.count).to be < 20 + expect(cursor).to be_nil + end + end + + it 'returns all tree entries in specific order during cursor pagination' do + collected_entries = [] + token = nil + + expected_entries = entries + + loop do + result, cursor = Gitlab::Git::Tree.where(repository, sha, path, recursive, { limit: 5, page_token: token }) + + collected_entries += result.entries + token = cursor&.next_cursor + + break if token.blank? + end + + expect(collected_entries.map(&:path)).to match_array(expected_entries.map(&:path)) + + expected_order = [ + collected_entries.select(&:dir?).map(&:path), + collected_entries.select(&:file?).map(&:path), + collected_entries.select(&:submodule?).map(&:path) + ].flatten - it 'does not support pagination' do - expect(entries.count).to be >= 10 - expect(cursor).to be_nil + expect(collected_entries.map(&:path)).to eq(expected_order) end end end |