summaryrefslogtreecommitdiff
path: root/spec/models/repository_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/repository_spec.rb')
-rw-r--r--spec/models/repository_spec.rb597
1 files changed, 594 insertions, 3 deletions
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index afbf62035ac..a57229a4fdf 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -5,6 +5,15 @@ describe Repository, models: true do
let(:repository) { create(:project).repository }
let(:user) { create(:user) }
+ let(:commit_options) do
+ author = repository.user_to_committer(user)
+ { message: 'Test message', committer: author, author: author }
+ end
+ let(:merge_commit) do
+ source_sha = repository.find_branch('feature').target
+ merge_commit_id = repository.merge(user, source_sha, 'master', commit_options)
+ repository.commit(merge_commit_id)
+ end
describe :branch_names_contains do
subject { repository.branch_names_contains(sample_commit.id) }
@@ -92,13 +101,29 @@ describe Repository, models: true do
end
describe 'parsing result' do
- subject { repository.parse_search_result(results.first) }
+ subject { repository.parse_search_result(search_result) }
+ let(:search_result) { results.first }
it { is_expected.to be_an OpenStruct }
it { expect(subject.filename).to eq('CHANGELOG') }
+ it { expect(subject.basename).to eq('CHANGELOG') }
it { expect(subject.ref).to eq('master') }
it { expect(subject.startline).to eq(186) }
it { expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") }
+
+ context "when filename has extension" do
+ let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" }
+
+ it { expect(subject.filename).to eq('CONTRIBUTE.md') }
+ it { expect(subject.basename).to eq('CONTRIBUTE') }
+ end
+
+ context "when file under directory" do
+ let(:search_result) { "master:a/b/c.md:5:a b c\n" }
+
+ it { expect(subject.filename).to eq('a/b/c.md') }
+ it { expect(subject.basename).to eq('a/b/c') }
+ end
end
end
@@ -139,6 +164,12 @@ describe Repository, models: true do
expect(branch.name).to eq('new_feature')
end
+
+ it 'calls the after_create_branch hook' do
+ expect(repository).to receive(:after_create_branch)
+
+ repository.add_branch(user, 'new_feature', 'master')
+ end
end
context 'when pre hooks failed' do
@@ -200,13 +231,22 @@ describe Repository, models: true do
describe :commit_with_hooks do
context 'when pre hooks were successful' do
- it 'should run without errors' do
- expect_any_instance_of(GitHooksService).to receive(:execute).and_return(true)
+ before do
+ expect_any_instance_of(GitHooksService).to receive(:execute).
+ and_return(true)
+ end
+ it 'should run without errors' do
expect do
repository.commit_with_hooks(user, 'feature') { sample_commit.id }
end.not_to raise_error
end
+
+ it 'should ensure the autocrlf Git option is set to :input' do
+ expect(repository).to receive(:update_autocrlf_option)
+
+ repository.commit_with_hooks(user, 'feature') { sample_commit.id }
+ end
end
context 'when pre hooks failed' do
@@ -219,4 +259,555 @@ describe Repository, models: true do
end
end
end
+
+ describe '#exists?' do
+ it 'returns true when a repository exists' do
+ expect(repository.exists?).to eq(true)
+ end
+
+ it 'returns false when a repository does not exist' do
+ expect(repository.raw_repository).to receive(:rugged).
+ and_raise(Gitlab::Git::Repository::NoRepository)
+
+ expect(repository.exists?).to eq(false)
+ end
+
+ it 'returns false when there is no namespace' do
+ allow(repository).to receive(:path_with_namespace).and_return(nil)
+
+ expect(repository.exists?).to eq(false)
+ end
+ end
+
+ describe '#has_visible_content?' do
+ subject { repository.has_visible_content? }
+
+ describe 'when there are no branches' do
+ before do
+ allow(repository.raw_repository).to receive(:branch_count).and_return(0)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ describe 'when there are branches' do
+ it 'returns true' do
+ expect(repository.raw_repository).to receive(:branch_count).and_return(3)
+
+ expect(subject).to eq(true)
+ end
+
+ it 'caches the output' do
+ expect(repository.raw_repository).to receive(:branch_count).
+ once.
+ and_return(3)
+
+ repository.has_visible_content?
+ repository.has_visible_content?
+ end
+ end
+ end
+
+ describe '#update_autocrlf_option' do
+ describe 'when autocrlf is not already set to :input' do
+ before do
+ repository.raw_repository.autocrlf = true
+ end
+
+ it 'sets autocrlf to :input' do
+ repository.update_autocrlf_option
+
+ expect(repository.raw_repository.autocrlf).to eq(:input)
+ end
+ end
+
+ describe 'when autocrlf is already set to :input' do
+ before do
+ repository.raw_repository.autocrlf = :input
+ end
+
+ it 'does nothing' do
+ expect(repository.raw_repository).to_not receive(:autocrlf=).
+ with(:input)
+
+ repository.update_autocrlf_option
+ end
+ end
+ end
+
+ describe '#empty?' do
+ let(:empty_repository) { create(:project_empty_repo).repository }
+
+ it 'returns true for an empty repository' do
+ expect(empty_repository.empty?).to eq(true)
+ end
+
+ it 'returns false for a non-empty repository' do
+ expect(repository.empty?).to eq(false)
+ end
+
+ it 'caches the output' do
+ expect(repository.raw_repository).to receive(:empty?).
+ once.
+ and_return(false)
+
+ repository.empty?
+ repository.empty?
+ end
+ end
+
+ describe '#root_ref' do
+ it 'returns a branch name' do
+ expect(repository.root_ref).to be_an_instance_of(String)
+ end
+
+ it 'caches the output' do
+ expect(repository.raw_repository).to receive(:root_ref).
+ once.
+ and_return('master')
+
+ repository.root_ref
+ repository.root_ref
+ end
+ end
+
+ describe '#expire_cache' do
+ it 'expires all caches' do
+ expect(repository).to receive(:expire_branch_cache)
+
+ repository.expire_cache
+ end
+
+ it 'expires the caches for a specific branch' do
+ expect(repository).to receive(:expire_branch_cache).with('master')
+
+ repository.expire_cache('master')
+ end
+
+ it 'expires the emptiness caches for an empty repository' do
+ expect(repository).to receive(:empty?).and_return(true)
+ expect(repository).to receive(:expire_emptiness_caches)
+
+ repository.expire_cache
+ end
+
+ it 'does not expire the emptiness caches for a non-empty repository' do
+ expect(repository).to receive(:empty?).and_return(false)
+ expect(repository).to_not receive(:expire_emptiness_caches)
+
+ repository.expire_cache
+ end
+ end
+
+ describe '#expire_root_ref_cache' do
+ it 'expires the root reference cache' do
+ repository.root_ref
+
+ expect(repository.raw_repository).to receive(:root_ref).
+ once.
+ and_return('foo')
+
+ repository.expire_root_ref_cache
+
+ expect(repository.root_ref).to eq('foo')
+ end
+ end
+
+ describe '#expire_has_visible_content_cache' do
+ it 'expires the visible content cache' do
+ repository.has_visible_content?
+
+ expect(repository.raw_repository).to receive(:branch_count).
+ once.
+ and_return(0)
+
+ repository.expire_has_visible_content_cache
+
+ expect(repository.has_visible_content?).to eq(false)
+ end
+ end
+
+ describe '#expire_branch_cache' do
+ # This method is private but we need it for testing purposes. Sadly there's
+ # no other proper way of testing caching operations.
+ let(:cache) { repository.send(:cache) }
+
+ it 'expires the cache for all branches' do
+ expect(cache).to receive(:expire).
+ at_least(repository.branches.length).
+ times
+
+ repository.expire_branch_cache
+ end
+
+ it 'expires the cache for all branches when the root branch is given' do
+ expect(cache).to receive(:expire).
+ at_least(repository.branches.length).
+ times
+
+ repository.expire_branch_cache(repository.root_ref)
+ end
+
+ it 'expires the cache for a specific branch' do
+ expect(cache).to receive(:expire).once
+
+ repository.expire_branch_cache('foo')
+ end
+ end
+
+ describe '#expire_emptiness_caches' do
+ let(:cache) { repository.send(:cache) }
+
+ it 'expires the caches' do
+ expect(cache).to receive(:expire).with(:empty?)
+ expect(repository).to receive(:expire_has_visible_content_cache)
+
+ repository.expire_emptiness_caches
+ end
+ end
+
+ describe :skip_merged_commit do
+ subject { repository.commits(Gitlab::Git::BRANCH_REF_PREFIX + "'test'", nil, 100, 0, true).map{ |k| k.id } }
+
+ it { is_expected.not_to include('e56497bb5f03a90a51293fc6d516788730953899') }
+ end
+
+ describe '#merge' do
+ it 'should merge the code and return 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
+ end
+
+ describe '#revert' do
+ let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
+ let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
+
+ context 'when there is a conflict' do
+ it 'should abort the operation' do
+ expect(repository.revert(user, new_image_commit, 'master')).to eq(false)
+ end
+ end
+
+ context 'when commit was already reverted' do
+ it 'should abort the operation' do
+ repository.revert(user, update_image_commit, 'master')
+
+ expect(repository.revert(user, update_image_commit, 'master')).to eq(false)
+ end
+ end
+
+ context 'when commit can be reverted' do
+ it 'should revert the changes' do
+ expect(repository.revert(user, update_image_commit, 'master')).to be_truthy
+ end
+ end
+
+ context 'reverting a merge commit' do
+ it 'should revert the changes' do
+ merge_commit
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).to be_present
+
+ repository.revert(user, merge_commit, 'master')
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
+ end
+ end
+ end
+
+ describe '#before_delete' do
+ describe 'when a repository does not exist' do
+ before do
+ allow(repository).to receive(:exists?).and_return(false)
+ end
+
+ it 'does not flush caches that depend on repository data' do
+ expect(repository).to_not receive(:expire_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the root ref cache' do
+ expect(repository).to receive(:expire_root_ref_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the emptiness caches' do
+ expect(repository).to receive(:expire_emptiness_caches)
+
+ repository.before_delete
+ end
+ end
+
+ describe 'when a repository exists' do
+ before do
+ allow(repository).to receive(:exists?).and_return(true)
+ end
+
+ it 'flushes the caches that depend on repository data' do
+ expect(repository).to receive(:expire_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the root ref cache' do
+ expect(repository).to receive(:expire_root_ref_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the emptiness caches' do
+ expect(repository).to receive(:expire_emptiness_caches)
+
+ repository.before_delete
+ end
+ end
+ end
+
+ describe '#before_change_head' do
+ it 'flushes the branch cache' do
+ expect(repository).to receive(:expire_branch_cache)
+
+ repository.before_change_head
+ end
+
+ it 'flushes the root ref cache' do
+ expect(repository).to receive(:expire_root_ref_cache)
+
+ repository.before_change_head
+ end
+ end
+
+ describe '#before_push_tag' do
+ it 'flushes the cache' do
+ expect(repository).to receive(:expire_cache)
+ expect(repository).to receive(:expire_tag_count_cache)
+
+ repository.before_push_tag
+ end
+ end
+
+ describe '#after_import' do
+ it 'flushes the emptiness cachess' do
+ expect(repository).to receive(:expire_emptiness_caches)
+
+ repository.after_import
+ end
+ end
+
+ describe '#after_push_commit' do
+ it 'flushes the cache' do
+ expect(repository).to receive(:expire_cache).with('master', '123')
+
+ repository.after_push_commit('master', '123')
+ end
+ end
+
+ describe '#after_create_branch' do
+ it 'flushes the visible content cache' do
+ expect(repository).to receive(:expire_has_visible_content_cache)
+
+ repository.after_create_branch
+ end
+ end
+
+ describe '#after_remove_branch' do
+ it 'flushes the visible content cache' do
+ expect(repository).to receive(:expire_has_visible_content_cache)
+
+ repository.after_remove_branch
+ end
+ end
+
+ describe "#main_language" do
+ it 'shows the main language of the project' do
+ expect(repository.main_language).to eq("Ruby")
+ end
+
+ it 'returns nil when the repository is empty' do
+ allow(repository).to receive(:empty?).and_return(true)
+
+ expect(repository.main_language).to be_nil
+ end
+ end
+
+ describe '#before_remove_tag' do
+ it 'flushes the tag cache' do
+ expect(repository).to receive(:expire_tag_count_cache)
+
+ repository.before_remove_tag
+ end
+ end
+
+ describe '#branch_count' do
+ it 'returns the number of branches' do
+ expect(repository.branch_count).to be_an_instance_of(Fixnum)
+ end
+ end
+
+ describe '#tag_count' do
+ it 'returns the number of tags' do
+ expect(repository.tag_count).to be_an_instance_of(Fixnum)
+ end
+ end
+
+ describe '#expire_branch_count_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ it 'expires the cache' do
+ expect(cache).to receive(:expire).with(:branch_count)
+
+ repository.expire_branch_count_cache
+ end
+ end
+
+ describe '#expire_tag_count_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ it 'expires the cache' do
+ expect(cache).to receive(:expire).with(:tag_count)
+
+ repository.expire_tag_count_cache
+ end
+ end
+
+ describe '#add_tag' do
+ it 'adds a tag' do
+ expect(repository).to receive(:before_push_tag)
+
+ expect_any_instance_of(Gitlab::Shell).to receive(:add_tag).
+ with(repository.path_with_namespace, '8.5', 'master', 'foo')
+
+ repository.add_tag('8.5', 'master', 'foo')
+ end
+ end
+
+ describe '#rm_branch' do
+ let(:user) { create(:user) }
+
+ it 'removes a branch' do
+ expect(repository).to receive(:before_remove_branch)
+ expect(repository).to receive(:after_remove_branch)
+
+ repository.rm_branch(user, 'feature')
+ end
+ end
+
+ describe '#rm_tag' do
+ it 'removes a tag' do
+ expect(repository).to receive(:before_remove_tag)
+
+ expect_any_instance_of(Gitlab::Shell).to receive(:rm_tag).
+ with(repository.path_with_namespace, '8.5')
+
+ repository.rm_tag('8.5')
+ end
+ end
+
+ describe '#avatar' do
+ it 'returns the first avatar file found in the repository' do
+ expect(repository).to receive(:blob_at_branch).
+ with('master', 'logo.png').
+ and_return(true)
+
+ expect(repository.avatar).to eq('logo.png')
+ end
+
+ it 'caches the output' do
+ allow(repository).to receive(:blob_at_branch).
+ with('master', 'logo.png').
+ and_return(true)
+
+ expect(repository.avatar).to eq('logo.png')
+
+ expect(repository).to_not receive(:blob_at_branch)
+ expect(repository.avatar).to eq('logo.png')
+ end
+ end
+
+ describe '#expire_avatar_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ before do
+ allow(repository).to receive(:cache).and_return(cache)
+ end
+
+ context 'without a branch or revision' do
+ it 'flushes the cache' do
+ expect(cache).to receive(:expire).with(:avatar)
+
+ repository.expire_avatar_cache
+ end
+ end
+
+ context 'with a branch' do
+ it 'does not flush the cache if the branch is not the default branch' do
+ expect(cache).not_to receive(:expire)
+
+ repository.expire_avatar_cache('cats')
+ end
+
+ it 'flushes the cache if the branch equals the default branch' do
+ expect(cache).to receive(:expire).with(:avatar)
+
+ repository.expire_avatar_cache(repository.root_ref)
+ end
+ end
+
+ context 'with a branch and revision' do
+ let(:commit) { double(:commit) }
+
+ before do
+ allow(repository).to receive(:commit).and_return(commit)
+ end
+
+ it 'does not flush the cache if the commit does not change any logos' do
+ diff = double(:diff, new_path: 'test.txt')
+
+ expect(commit).to receive(:diffs).and_return([diff])
+ expect(cache).not_to receive(:expire)
+
+ repository.expire_avatar_cache(repository.root_ref, '123')
+ end
+
+ it 'flushes the cache if the commit changes any of the logos' do
+ diff = double(:diff, new_path: Repository::AVATAR_FILES[0])
+
+ expect(commit).to receive(:diffs).and_return([diff])
+ expect(cache).to receive(:expire).with(:avatar)
+
+ repository.expire_avatar_cache(repository.root_ref, '123')
+ end
+ end
+ end
+
+ describe '#build_cache' do
+ let(:cache) { repository.send(:cache) }
+
+ it 'builds the caches if they do not already exist' do
+ expect(cache).to receive(:exist?).
+ exactly(repository.cache_keys.length).
+ times.
+ and_return(false)
+
+ repository.cache_keys.each do |key|
+ expect(repository).to receive(key)
+ end
+
+ repository.build_cache
+ end
+
+ it 'does not build any caches that already exist' do
+ expect(cache).to receive(:exist?).
+ exactly(repository.cache_keys.length).
+ times.
+ and_return(true)
+
+ repository.cache_keys.each do |key|
+ expect(repository).to_not receive(key)
+ end
+
+ repository.build_cache
+ end
+ end
end