summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab')
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb233
-rw-r--r--spec/lib/gitlab/ci/external/file/local_spec.rb78
-rw-r--r--spec/lib/gitlab/ci/external/file/remote_spec.rb114
-rw-r--r--spec/lib/gitlab/ci/external/mapper_spec.rb96
-rw-r--r--spec/lib/gitlab/ci/external/processor_spec.rb182
-rw-r--r--spec/lib/gitlab/cleanup/project_uploads_spec.rb2
-rw-r--r--spec/lib/gitlab/contributions_calendar_spec.rb17
-rw-r--r--spec/lib/gitlab/diff/highlight_cache_spec.rb70
-rw-r--r--spec/lib/gitlab/git/committer_with_hooks_spec.rb156
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb82
-rw-r--r--spec/lib/gitlab/git/gitlab_projects_spec.rb321
-rw-r--r--spec/lib/gitlab/git/hook_spec.rb111
-rw-r--r--spec/lib/gitlab/git/hooks_service_spec.rb50
-rw-r--r--spec/lib/gitlab/git/index_spec.rb239
-rw-r--r--spec/lib/gitlab/git/popen_spec.rb179
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb774
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb18
-rw-r--r--spec/lib/gitlab/gitaly_client/remote_service_spec.rb20
-rw-r--r--spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_object_storage_spec.rb105
-rw-r--r--spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb3
-rw-r--r--spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb31
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml9
-rw-r--r--spec/lib/gitlab/import_export/avatar_restorer_spec.rb33
-rw-r--r--spec/lib/gitlab/import_export/avatar_saver_spec.rb5
-rw-r--r--spec/lib/gitlab/import_export/file_importer_object_storage_spec.rb89
-rw-r--r--spec/lib/gitlab/import_export/file_importer_spec.rb12
-rw-r--r--spec/lib/gitlab/import_export/importer_object_storage_spec.rb115
-rw-r--r--spec/lib/gitlab/import_export/importer_spec.rb15
-rw-r--r--spec/lib/gitlab/import_export/model_configuration_spec.rb42
-rw-r--r--spec/lib/gitlab/import_export/project.json33
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb8
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb11
-rw-r--r--spec/lib/gitlab/import_export/repo_restorer_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml21
-rw-r--r--spec/lib/gitlab/import_export/saver_spec.rb24
-rw-r--r--spec/lib/gitlab/import_export/uploads_manager_spec.rb43
-rw-r--r--spec/lib/gitlab/import_export/uploads_restorer_spec.rb10
-rw-r--r--spec/lib/gitlab/import_export/uploads_saver_spec.rb1
-rw-r--r--spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb2
-rw-r--r--spec/lib/gitlab/prometheus/metric_group_spec.rb41
-rw-r--r--spec/lib/gitlab/shell_spec.rb5
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb16
42 files changed, 1320 insertions, 2102 deletions
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 5a78ce783dd..b43aca8a354 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -124,4 +124,237 @@ describe Gitlab::Ci::Config do
end
end
end
+
+ context "when using 'include' directive" do
+ let(:project) { create(:project, :repository) }
+ let(:remote_location) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:local_location) { 'spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml' }
+
+ let(:remote_file_content) do
+ <<~HEREDOC
+ variables:
+ AUTO_DEVOPS_DOMAIN: domain.example.com
+ POSTGRES_USER: user
+ POSTGRES_PASSWORD: testing-password
+ POSTGRES_ENABLED: "true"
+ POSTGRES_DB: $CI_ENVIRONMENT_SLUG
+ HEREDOC
+ end
+
+ let(:local_file_content) do
+ File.read(Rails.root.join(local_location))
+ end
+
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - #{local_location}
+ - #{remote_location}
+
+ image: ruby:2.2
+ HEREDOC
+ end
+
+ let(:config) do
+ described_class.new(gitlab_ci_yml, project: project, sha: '12345')
+ end
+
+ before do
+ WebMock.stub_request(:get, remote_location)
+ .to_return(body: remote_file_content)
+
+ allow(project.repository)
+ .to receive(:blob_data_at).and_return(local_file_content)
+ end
+
+ context "when gitlab_ci_yml has valid 'include' defined" do
+ it 'should return a composed hash' do
+ before_script_values = [
+ "apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs", "ruby -v",
+ "which ruby",
+ "gem install bundler --no-ri --no-rdoc",
+ "bundle install --jobs $(nproc) \"${FLAGS[@]}\""
+ ]
+ variables = {
+ AUTO_DEVOPS_DOMAIN: "domain.example.com",
+ POSTGRES_USER: "user",
+ POSTGRES_PASSWORD: "testing-password",
+ POSTGRES_ENABLED: "true",
+ POSTGRES_DB: "$CI_ENVIRONMENT_SLUG"
+ }
+ composed_hash = {
+ before_script: before_script_values,
+ image: "ruby:2.2",
+ rspec: { script: ["bundle exec rspec"] },
+ variables: variables
+ }
+
+ expect(config.to_hash).to eq(composed_hash)
+ end
+ end
+
+ context "when gitlab_ci.yml has invalid 'include' defined" do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include: invalid
+ HEREDOC
+ end
+
+ it 'raises error YamlProcessor validationError' do
+ expect { config }.to raise_error(
+ ::Gitlab::Ci::YamlProcessor::ValidationError,
+ "Local file 'invalid' is not valid."
+ )
+ end
+ end
+
+ describe 'external file version' do
+ context 'when external local file SHA is defined' do
+ it 'is using a defined value' do
+ expect(project.repository).to receive(:blob_data_at)
+ .with('eeff1122', local_location)
+
+ described_class.new(gitlab_ci_yml, project: project, sha: 'eeff1122')
+ end
+ end
+
+ context 'when external local file SHA is not defined' do
+ it 'is using latest SHA on the default branch' do
+ expect(project.repository).to receive(:root_ref_sha)
+
+ described_class.new(gitlab_ci_yml, project: project)
+ end
+ end
+ end
+
+ context "when both external files and gitlab_ci.yml defined the same key" do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - #{remote_location}
+
+ image: ruby:2.2
+ HEREDOC
+ end
+
+ let(:remote_file_content) do
+ <<~HEREDOC
+ image: php:5-fpm-alpine
+ HEREDOC
+ end
+
+ it 'should take precedence' do
+ expect(config.to_hash).to eq({ image: 'ruby:2.2' })
+ end
+ end
+
+ context "when both external files and gitlab_ci.yml define a dictionary of distinct variables" do
+ let(:remote_file_content) do
+ <<~HEREDOC
+ variables:
+ A: 'alpha'
+ B: 'beta'
+ HEREDOC
+ end
+
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - #{remote_location}
+
+ variables:
+ C: 'gamma'
+ D: 'delta'
+ HEREDOC
+ end
+
+ it 'should merge the variables dictionaries' do
+ expect(config.to_hash).to eq({ variables: { A: 'alpha', B: 'beta', C: 'gamma', D: 'delta' } })
+ end
+ end
+
+ context "when both external files and gitlab_ci.yml define a dictionary of overlapping variables" do
+ let(:remote_file_content) do
+ <<~HEREDOC
+ variables:
+ A: 'alpha'
+ B: 'beta'
+ C: 'omnicron'
+ HEREDOC
+ end
+
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - #{remote_location}
+
+ variables:
+ C: 'gamma'
+ D: 'delta'
+ HEREDOC
+ end
+
+ it 'later declarations should take precedence' do
+ expect(config.to_hash).to eq({ variables: { A: 'alpha', B: 'beta', C: 'gamma', D: 'delta' } })
+ end
+ end
+
+ context 'when both external files and gitlab_ci.yml define a job' do
+ let(:remote_file_content) do
+ <<~HEREDOC
+ job1:
+ script:
+ - echo 'hello from remote file'
+ HEREDOC
+ end
+
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - #{remote_location}
+
+ job1:
+ variables:
+ VARIABLE_DEFINED_IN_MAIN_FILE: 'some value'
+ HEREDOC
+ end
+
+ it 'merges the jobs' do
+ expect(config.to_hash).to eq({
+ job1: {
+ script: ["echo 'hello from remote file'"],
+ variables: {
+ VARIABLE_DEFINED_IN_MAIN_FILE: 'some value'
+ }
+ }
+ })
+ end
+
+ context 'when the script key is in both' do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - #{remote_location}
+
+ job1:
+ script:
+ - echo 'hello from main file'
+ variables:
+ VARIABLE_DEFINED_IN_MAIN_FILE: 'some value'
+ HEREDOC
+ end
+
+ it 'uses the script from the gitlab_ci.yml' do
+ expect(config.to_hash).to eq({
+ job1: {
+ script: ["echo 'hello from main file'"],
+ variables: {
+ VARIABLE_DEFINED_IN_MAIN_FILE: 'some value'
+ }
+ }
+ })
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/external/file/local_spec.rb b/spec/lib/gitlab/ci/external/file/local_spec.rb
new file mode 100644
index 00000000000..3f32d81a827
--- /dev/null
+++ b/spec/lib/gitlab/ci/external/file/local_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::External::File::Local do
+ let(:project) { create(:project, :repository) }
+ let(:local_file) { described_class.new(location, { project: project, sha: '12345' }) }
+
+ describe '#valid?' do
+ context 'when is a valid local path' do
+ let(:location) { '/vendor/gitlab-ci-yml/existent-file.yml' }
+
+ before do
+ allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return("image: 'ruby2:2'")
+ end
+
+ it 'should return true' do
+ expect(local_file.valid?).to be_truthy
+ end
+ end
+
+ context 'when is not a valid local path' do
+ let(:location) { '/vendor/gitlab-ci-yml/non-existent-file.yml' }
+
+ it 'should return false' do
+ expect(local_file.valid?).to be_falsy
+ end
+ end
+
+ context 'when is not a yaml file' do
+ let(:location) { '/config/application.rb' }
+
+ it 'should return false' do
+ expect(local_file.valid?).to be_falsy
+ end
+ end
+ end
+
+ describe '#content' do
+ context 'with a a valid file' do
+ let(:local_file_content) do
+ <<~HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+ HEREDOC
+ end
+ let(:location) { '/vendor/gitlab-ci-yml/existent-file.yml' }
+
+ before do
+ allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return(local_file_content)
+ end
+
+ it 'should return the content of the file' do
+ expect(local_file.content).to eq(local_file_content)
+ end
+ end
+
+ context 'with an invalid file' do
+ let(:location) { '/vendor/gitlab-ci-yml/non-existent-file.yml' }
+
+ it 'should be nil' do
+ expect(local_file.content).to be_nil
+ end
+ end
+ end
+
+ describe '#error_message' do
+ let(:location) { '/vendor/gitlab-ci-yml/non-existent-file.yml' }
+
+ it 'should return an error message' do
+ expect(local_file.error_message).to eq("Local file '#{location}' is not valid.")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/external/file/remote_spec.rb b/spec/lib/gitlab/ci/external/file/remote_spec.rb
new file mode 100644
index 00000000000..b1819c8960b
--- /dev/null
+++ b/spec/lib/gitlab/ci/external/file/remote_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::External::File::Remote do
+ let(:remote_file) { described_class.new(location) }
+ let(:location) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:remote_file_content) do
+ <<~HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+ HEREDOC
+ end
+
+ describe "#valid?" do
+ context 'when is a valid remote url' do
+ before do
+ WebMock.stub_request(:get, location).to_return(body: remote_file_content)
+ end
+
+ it 'should return true' do
+ expect(remote_file.valid?).to be_truthy
+ end
+ end
+
+ context 'with an irregular url' do
+ let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+
+ it 'should return false' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+
+ context 'with a timeout' do
+ before do
+ allow(Gitlab::HTTP).to receive(:get).and_raise(Timeout::Error)
+ end
+
+ it 'should be falsy' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+
+ context 'when is not a yaml file' do
+ let(:location) { 'https://asdasdasdaj48ggerexample.com' }
+
+ it 'should be falsy' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+
+ context 'with an internal url' do
+ let(:location) { 'http://localhost:8080' }
+
+ it 'should be falsy' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+ end
+
+ describe "#content" do
+ context 'with a valid remote file' do
+ before do
+ WebMock.stub_request(:get, location).to_return(body: remote_file_content)
+ end
+
+ it 'should return the content of the file' do
+ expect(remote_file.content).to eql(remote_file_content)
+ end
+ end
+
+ context 'with a timeout' do
+ before do
+ allow(Gitlab::HTTP).to receive(:get).and_raise(Timeout::Error)
+ end
+
+ it 'should be falsy' do
+ expect(remote_file.content).to be_falsy
+ end
+ end
+
+ context 'with an invalid remote url' do
+ let(:location) { 'https://asdasdasdaj48ggerexample.com' }
+
+ before do
+ WebMock.stub_request(:get, location).to_raise(SocketError.new('Some HTTP error'))
+ end
+
+ it 'should be nil' do
+ expect(remote_file.content).to be_nil
+ end
+ end
+
+ context 'with an internal url' do
+ let(:location) { 'http://localhost:8080' }
+
+ it 'should be nil' do
+ expect(remote_file.content).to be_nil
+ end
+ end
+ end
+
+ describe "#error_message" do
+ let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+
+ it 'should return an error message' do
+ expect(remote_file.error_message).to eq("Remote file '#{location}' is not valid.")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/external/mapper_spec.rb b/spec/lib/gitlab/ci/external/mapper_spec.rb
new file mode 100644
index 00000000000..6270d27a36d
--- /dev/null
+++ b/spec/lib/gitlab/ci/external/mapper_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::External::Mapper do
+ let(:project) { create(:project, :repository) }
+ let(:file_content) do
+ <<~HEREDOC
+ image: 'ruby:2.2'
+ HEREDOC
+ end
+
+ describe '#process' do
+ subject { described_class.new(values, project, '123456').process }
+
+ context "when 'include' keyword is defined as string" do
+ context 'when the string is a local file' do
+ let(:values) do
+ {
+ include: '/vendor/gitlab-ci-yml/non-existent-file.yml',
+ image: 'ruby:2.2'
+ }
+ end
+
+ it 'returns an array' do
+ expect(subject).to be_an(Array)
+ end
+
+ it 'returns File instances' do
+ expect(subject.first).to be_an_instance_of(Gitlab::Ci::External::File::Local)
+ end
+ end
+
+ context 'when the string is a remote file' do
+ let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) do
+ {
+ include: remote_url,
+ image: 'ruby:2.2'
+ }
+ end
+
+ before do
+ WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ end
+
+ it 'returns an array' do
+ expect(subject).to be_an(Array)
+ end
+
+ it 'returns File instances' do
+ expect(subject.first).to be_an_instance_of(Gitlab::Ci::External::File::Remote)
+ end
+ end
+ end
+
+ context "when 'include' is defined as an array" do
+ let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) do
+ {
+ include:
+ [
+ remote_url,
+ '/vendor/gitlab-ci-yml/template.yml'
+ ],
+ image: 'ruby:2.2'
+ }
+ end
+
+ before do
+ WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ end
+
+ it 'returns an array' do
+ expect(subject).to be_an(Array)
+ end
+
+ it 'returns Files instances' do
+ expect(subject).to all(respond_to(:valid?))
+ expect(subject).to all(respond_to(:content))
+ end
+ end
+
+ context "when 'include' is not defined" do
+ let(:values) do
+ {
+ image: 'ruby:2.2'
+ }
+ end
+
+ it 'returns an empty array' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/external/processor_spec.rb b/spec/lib/gitlab/ci/external/processor_spec.rb
new file mode 100644
index 00000000000..688c2b3c8aa
--- /dev/null
+++ b/spec/lib/gitlab/ci/external/processor_spec.rb
@@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::External::Processor do
+ let(:project) { create(:project, :repository) }
+ let(:processor) { described_class.new(values, project, '12345') }
+
+ describe "#perform" do
+ context 'when no external files defined' do
+ let(:values) { { image: 'ruby:2.2' } }
+
+ it 'should return the same values' do
+ expect(processor.perform).to eq(values)
+ end
+ end
+
+ context 'when an invalid local file is defined' do
+ let(:values) { { include: '/vendor/gitlab-ci-yml/non-existent-file.yml', image: 'ruby:2.2' } }
+
+ it 'should raise an error' do
+ expect { processor.perform }.to raise_error(
+ described_class::FileError,
+ "Local file '/vendor/gitlab-ci-yml/non-existent-file.yml' is not valid."
+ )
+ end
+ end
+
+ context 'when an invalid remote file is defined' do
+ let(:remote_file) { 'http://doesntexist.com/.gitlab-ci-1.yml' }
+ let(:values) { { include: remote_file, image: 'ruby:2.2' } }
+
+ before do
+ WebMock.stub_request(:get, remote_file).to_raise(SocketError.new('Some HTTP error'))
+ end
+
+ it 'should raise an error' do
+ expect { processor.perform }.to raise_error(
+ described_class::FileError,
+ "Remote file '#{remote_file}' is not valid."
+ )
+ end
+ end
+
+ context 'with a valid remote external file is defined' do
+ let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) { { include: remote_file, image: 'ruby:2.2' } }
+ let(:external_file_content) do
+ <<-HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+
+ rspec:
+ script:
+ - bundle exec rspec
+
+ rubocop:
+ script:
+ - bundle exec rubocop
+ HEREDOC
+ end
+
+ before do
+ WebMock.stub_request(:get, remote_file).to_return(body: external_file_content)
+ end
+
+ it 'should append the file to the values' do
+ output = processor.perform
+ expect(output.keys).to match_array([:image, :before_script, :rspec, :rubocop])
+ end
+
+ it "should remove the 'include' keyword" do
+ expect(processor.perform[:include]).to be_nil
+ end
+ end
+
+ context 'with a valid local external file is defined' do
+ let(:values) { { include: '/vendor/gitlab-ci-yml/template.yml', image: 'ruby:2.2' } }
+ let(:local_file_content) do
+ <<-HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+ HEREDOC
+ end
+
+ before do
+ allow_any_instance_of(Gitlab::Ci::External::File::Local).to receive(:fetch_local_content).and_return(local_file_content)
+ end
+
+ it 'should append the file to the values' do
+ output = processor.perform
+ expect(output.keys).to match_array([:image, :before_script])
+ end
+
+ it "should remove the 'include' keyword" do
+ expect(processor.perform[:include]).to be_nil
+ end
+ end
+
+ context 'with multiple external files are defined' do
+ let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:external_files) do
+ [
+ '/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml',
+ remote_file
+ ]
+ end
+ let(:values) do
+ {
+ include: external_files,
+ image: 'ruby:2.2'
+ }
+ end
+
+ let(:remote_file_content) do
+ <<-HEREDOC
+ stages:
+ - build
+ - review
+ - cleanup
+ HEREDOC
+ end
+
+ before do
+ local_file_content = File.read(Rails.root.join('spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml'))
+ allow_any_instance_of(Gitlab::Ci::External::File::Local).to receive(:fetch_local_content).and_return(local_file_content)
+ WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
+ end
+
+ it 'should append the files to the values' do
+ expect(processor.perform.keys).to match_array([:image, :stages, :before_script, :rspec])
+ end
+
+ it "should remove the 'include' keyword" do
+ expect(processor.perform[:include]).to be_nil
+ end
+ end
+
+ context 'when external files are defined but not valid' do
+ let(:values) { { include: '/vendor/gitlab-ci-yml/template.yml', image: 'ruby:2.2' } }
+
+ let(:local_file_content) { 'invalid content file ////' }
+
+ before do
+ allow_any_instance_of(Gitlab::Ci::External::File::Local).to receive(:fetch_local_content).and_return(local_file_content)
+ end
+
+ it 'should raise an error' do
+ expect { processor.perform }.to raise_error(Gitlab::Ci::Config::Loader::FormatError)
+ end
+ end
+
+ context "when both external files and values defined the same key" do
+ let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) do
+ {
+ include: remote_file,
+ image: 'ruby:2.2'
+ }
+ end
+
+ let(:remote_file_content) do
+ <<~HEREDOC
+ image: php:5-fpm-alpine
+ HEREDOC
+ end
+
+ it 'should take precedence' do
+ WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
+ expect(processor.perform[:image]).to eq('ruby:2.2')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/cleanup/project_uploads_spec.rb b/spec/lib/gitlab/cleanup/project_uploads_spec.rb
index 11e605eece6..bf130b8fabd 100644
--- a/spec/lib/gitlab/cleanup/project_uploads_spec.rb
+++ b/spec/lib/gitlab/cleanup/project_uploads_spec.rb
@@ -132,7 +132,6 @@ describe Gitlab::Cleanup::ProjectUploads do
let!(:path) { File.join(FileUploader.root, orphaned.model.full_path, orphaned.path) }
before do
- stub_feature_flags(import_export_object_storage: true)
stub_uploads_object_storage(FileUploader)
FileUtils.mkdir_p(File.dirname(path))
@@ -156,7 +155,6 @@ describe Gitlab::Cleanup::ProjectUploads do
let!(:new_path) { File.join(FileUploader.root, '-', 'project-lost-found', 'wrong', orphaned.path) }
before do
- stub_feature_flags(import_export_object_storage: true)
stub_uploads_object_storage(FileUploader)
FileUtils.mkdir_p(File.dirname(path))
diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb
index 2c63f3b0455..6d29044ffd5 100644
--- a/spec/lib/gitlab/contributions_calendar_spec.rb
+++ b/spec/lib/gitlab/contributions_calendar_spec.rb
@@ -62,13 +62,16 @@ describe Gitlab::ContributionsCalendar do
expect(calendar.activity_dates).to eq(last_week => 2, today => 1)
end
- it "only shows private events to authorized users" do
- create_event(private_project, today)
- create_event(feature_project, today)
+ context "when the user has opted-in for private contributions" do
+ it "shows private and public events to all users" do
+ user.update_column(:include_private_contributions, true)
+ create_event(private_project, today)
+ create_event(public_project, today)
- expect(calendar.activity_dates[today]).to eq(0)
- expect(calendar(user).activity_dates[today]).to eq(0)
- expect(calendar(contributor).activity_dates[today]).to eq(2)
+ expect(calendar.activity_dates[today]).to eq(1)
+ expect(calendar(user).activity_dates[today]).to eq(1)
+ expect(calendar(contributor).activity_dates[today]).to eq(2)
+ end
end
it "counts the diff notes on merge request" do
@@ -128,7 +131,7 @@ describe Gitlab::ContributionsCalendar do
e3 = create_event(feature_project, today)
create_event(public_project, last_week)
- expect(calendar.events_by_date(today)).to contain_exactly(e1)
+ expect(calendar.events_by_date(today)).to contain_exactly(e1, e3)
expect(calendar(contributor).events_by_date(today)).to contain_exactly(e1, e2, e3)
end
diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb
new file mode 100644
index 00000000000..bfcfed4231f
--- /dev/null
+++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Diff::HighlightCache do
+ let(:merge_request) { create(:merge_request_with_diffs) }
+
+ subject(:cache) { described_class.new(merge_request.diffs, backend: backend) }
+
+ describe '#decorate' do
+ let(:backend) { double('backend').as_null_object }
+
+ # Manually creates a Diff::File object to avoid triggering the cache on
+ # the FileCollection::MergeRequestDiff
+ let(:diff_file) do
+ diffs = merge_request.diffs
+ raw_diff = diffs.diffable.raw_diffs(diffs.diff_options.merge(paths: ['CHANGELOG'])).first
+ Gitlab::Diff::File.new(raw_diff,
+ repository: diffs.project.repository,
+ diff_refs: diffs.diff_refs,
+ fallback_diff_refs: diffs.fallback_diff_refs)
+ end
+
+ it 'does not calculate highlighting when reading from cache' do
+ cache.write_if_empty
+ cache.decorate(diff_file)
+
+ expect_any_instance_of(Gitlab::Diff::Highlight).not_to receive(:highlight)
+
+ diff_file.highlighted_diff_lines
+ end
+
+ it 'assigns highlighted diff lines to the DiffFile' do
+ cache.write_if_empty
+ cache.decorate(diff_file)
+
+ expect(diff_file.highlighted_diff_lines.size).to be > 5
+ end
+
+ it 'submits a single reading from the cache' do
+ cache.decorate(diff_file)
+ cache.decorate(diff_file)
+
+ expect(backend).to have_received(:read).with(cache.key).once
+ end
+ end
+
+ describe '#write_if_empty' do
+ let(:backend) { double('backend', read: {}).as_null_object }
+
+ it 'submits a single writing to the cache' do
+ cache.write_if_empty
+ cache.write_if_empty
+
+ expect(backend).to have_received(:write).with(cache.key,
+ hash_including('CHANGELOG-false-false-false'),
+ expires_in: 1.week).once
+ end
+ end
+
+ describe '#clear' do
+ let(:backend) { double('backend').as_null_object }
+
+ it 'clears cache' do
+ cache.clear
+
+ expect(backend).to have_received(:delete).with(cache.key)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/committer_with_hooks_spec.rb b/spec/lib/gitlab/git/committer_with_hooks_spec.rb
deleted file mode 100644
index c7626058acd..00000000000
--- a/spec/lib/gitlab/git/committer_with_hooks_spec.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::CommitterWithHooks, :seed_helper do
- # TODO https://gitlab.com/gitlab-org/gitaly/issues/1234
- skip 'needs to be moved to gitaly-ruby test suite' do
- shared_examples 'calling wiki hooks' do
- let(:project) { create(:project) }
- let(:user) { project.owner }
- let(:project_wiki) { ProjectWiki.new(project, user) }
- let(:wiki) { project_wiki.wiki }
- let(:options) do
- {
- id: user.id,
- username: user.username,
- name: user.name,
- email: user.email,
- message: 'commit message'
- }
- end
-
- subject { described_class.new(wiki, options) }
-
- before do
- project_wiki.create_page('home', 'test content')
- end
-
- shared_examples 'failing pre-receive hook' do
- before do
- expect_any_instance_of(Gitlab::Git::HooksService).to receive(:run_hook).with('pre-receive').and_return([false, ''])
- expect_any_instance_of(Gitlab::Git::HooksService).not_to receive(:run_hook).with('update')
- expect_any_instance_of(Gitlab::Git::HooksService).not_to receive(:run_hook).with('post-receive')
- end
-
- it 'raises exception' do
- expect { subject.commit }.to raise_error(Gitlab::Git::Wiki::OperationError)
- end
-
- it 'does not create a new commit inside the repository' do
- current_rev = find_current_rev
-
- expect { subject.commit }.to raise_error(Gitlab::Git::Wiki::OperationError)
-
- expect(current_rev).to eq find_current_rev
- end
- end
-
- shared_examples 'failing update hook' do
- before do
- expect_any_instance_of(Gitlab::Git::HooksService).to receive(:run_hook).with('pre-receive').and_return([true, ''])
- expect_any_instance_of(Gitlab::Git::HooksService).to receive(:run_hook).with('update').and_return([false, ''])
- expect_any_instance_of(Gitlab::Git::HooksService).not_to receive(:run_hook).with('post-receive')
- end
-
- it 'raises exception' do
- expect { subject.commit }.to raise_error(Gitlab::Git::Wiki::OperationError)
- end
-
- it 'does not create a new commit inside the repository' do
- current_rev = find_current_rev
-
- expect { subject.commit }.to raise_error(Gitlab::Git::Wiki::OperationError)
-
- expect(current_rev).to eq find_current_rev
- end
- end
-
- shared_examples 'failing post-receive hook' do
- before do
- expect_any_instance_of(Gitlab::Git::HooksService).to receive(:run_hook).with('pre-receive').and_return([true, ''])
- expect_any_instance_of(Gitlab::Git::HooksService).to receive(:run_hook).with('update').and_return([true, ''])
- expect_any_instance_of(Gitlab::Git::HooksService).to receive(:run_hook).with('post-receive').and_return([false, ''])
- end
-
- it 'does not raise exception' do
- expect { subject.commit }.not_to raise_error
- end
-
- it 'creates the commit' do
- current_rev = find_current_rev
-
- subject.commit
-
- expect(current_rev).not_to eq find_current_rev
- end
- end
-
- shared_examples 'when hooks call succceeds' do
- let(:hook) { double(:hook) }
-
- it 'calls the three hooks' do
- expect(Gitlab::Git::Hook).to receive(:new).exactly(3).times.and_return(hook)
- expect(hook).to receive(:trigger).exactly(3).times.and_return([true, nil])
-
- subject.commit
- end
-
- it 'creates the commit' do
- current_rev = find_current_rev
-
- subject.commit
-
- expect(current_rev).not_to eq find_current_rev
- end
- end
-
- context 'when creating a page' do
- before do
- project_wiki.create_page('index', 'test content')
- end
-
- it_behaves_like 'failing pre-receive hook'
- it_behaves_like 'failing update hook'
- it_behaves_like 'failing post-receive hook'
- it_behaves_like 'when hooks call succceeds'
- end
-
- context 'when updating a page' do
- before do
- project_wiki.update_page(find_page('home'), content: 'some other content', format: :markdown)
- end
-
- it_behaves_like 'failing pre-receive hook'
- it_behaves_like 'failing update hook'
- it_behaves_like 'failing post-receive hook'
- it_behaves_like 'when hooks call succceeds'
- end
-
- context 'when deleting a page' do
- before do
- project_wiki.delete_page(find_page('home'))
- end
-
- it_behaves_like 'failing pre-receive hook'
- it_behaves_like 'failing update hook'
- it_behaves_like 'failing post-receive hook'
- it_behaves_like 'when hooks call succceeds'
- end
-
- def find_current_rev
- wiki.gollum_wiki.repo.commits.first&.sha
- end
-
- def find_page(name)
- wiki.page(title: name)
- end
- end
-
- context 'when Gitaly is enabled' do
- it_behaves_like 'calling wiki hooks'
- end
-
- context 'when Gitaly is disabled', :disable_gitaly do
- it_behaves_like 'calling wiki hooks'
- end
- end
-end
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 87d9fcee39e..27d803e0117 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -2,12 +2,24 @@ require "spec_helper"
describe Gitlab::Git::Diff, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:gitaly_diff) do
+ Gitlab::GitalyClient::Diff.new(
+ from_path: '.gitmodules',
+ to_path: '.gitmodules',
+ old_mode: 0100644,
+ new_mode: 0100644,
+ from_id: '0792c58905eff3432b721f8c4a64363d8e28d9ae',
+ to_id: 'efd587ccb47caf5f31fc954edb21f0a713d9ecc3',
+ overflow_marker: false,
+ collapsed: false,
+ too_large: false,
+ patch: "@@ -4,3 +4,6 @@\n [submodule \"gitlab-shell\"]\n \tpath = gitlab-shell\n \turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n"
+ )
+ end
before do
@raw_diff_hash = {
diff: <<EOT.gsub(/^ {8}/, "").sub(/\n$/, ""),
- --- a/.gitmodules
- +++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "gitlab-shell"]
\tpath = gitlab-shell
@@ -26,12 +38,6 @@ EOT
deleted_file: false,
too_large: false
}
-
- # TODO use a Gitaly diff object instead
- @rugged_diff = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.diff("5937ac0a7beb003549fc5fd26fc247adbce4a52e^", "5937ac0a7beb003549fc5fd26fc247adbce4a52e", paths:
- [".gitmodules"]).patches.first
- end
end
describe '.new' do
@@ -60,7 +66,7 @@ EOT
context 'using a Rugged::Patch' do
context 'with a small diff' do
- let(:diff) { described_class.new(@rugged_diff) }
+ let(:diff) { described_class.new(gitaly_diff) }
it 'initializes the diff' do
expect(diff.to_hash).to eq(@raw_diff_hash)
@@ -73,10 +79,8 @@ EOT
context 'using a diff that is too large' do
it 'prunes the diff' do
- expect_any_instance_of(String).to receive(:bytesize)
- .and_return(1024 * 1024 * 1024)
-
- diff = described_class.new(@rugged_diff)
+ gitaly_diff.too_large = true
+ diff = described_class.new(gitaly_diff)
expect(diff.diff).to be_empty
expect(diff).to be_too_large
@@ -84,33 +88,15 @@ EOT
end
context 'using a collapsable diff that is too large' do
- before do
- # The patch total size is 200, with lines between 21 and 54.
- # This is a quick-and-dirty way to test this. Ideally, a new patch is
- # added to the test repo with a size that falls between the real limits.
- stub_const("#{described_class}::SIZE_LIMIT", 150)
- stub_const("#{described_class}::COLLAPSE_LIMIT", 100)
- end
-
it 'prunes the diff as a large diff instead of as a collapsed diff' do
- diff = described_class.new(@rugged_diff, expanded: false)
+ gitaly_diff.too_large = true
+ diff = described_class.new(gitaly_diff, expanded: false)
expect(diff.diff).to be_empty
expect(diff).to be_too_large
expect(diff).not_to be_collapsed
end
end
-
- context 'using a large binary diff' do
- it 'does not prune the diff' do
- expect_any_instance_of(Rugged::Diff::Delta).to receive(:binary?)
- .and_return(true)
-
- diff = described_class.new(@rugged_diff)
-
- expect(diff.diff).not_to be_empty
- end
- end
end
context 'using a GitalyClient::Diff' do
@@ -259,31 +245,37 @@ EOT
end
it 'leave non-binary diffs as-is' do
- diff = described_class.new(@rugged_diff)
+ diff = described_class.new(gitaly_diff)
expect(diff.json_safe_diff).to eq(diff.diff)
end
end
describe '#submodule?' do
- before do
- # TODO use a Gitaly diff object instead
- rugged_commit = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.rev_parse('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
- end
-
- @diffs = rugged_commit.parents[0].diff(rugged_commit).patches
+ let(:gitaly_submodule_diff) do
+ Gitlab::GitalyClient::Diff.new(
+ from_path: 'gitlab-grack',
+ to_path: 'gitlab-grack',
+ old_mode: 0,
+ new_mode: 57344,
+ from_id: '0000000000000000000000000000000000000000',
+ to_id: '645f6c4c82fd3f5e06f67134450a570b795e55a6',
+ overflow_marker: false,
+ collapsed: false,
+ too_large: false,
+ patch: "@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n"
+ )
end
- it { expect(described_class.new(@diffs[0]).submodule?).to eq(false) }
- it { expect(described_class.new(@diffs[1]).submodule?).to eq(true) }
+ it { expect(described_class.new(gitaly_diff).submodule?).to eq(false) }
+ it { expect(described_class.new(gitaly_submodule_diff).submodule?).to eq(true) }
end
describe '#line_count' do
it 'returns the correct number of lines' do
- diff = described_class.new(@rugged_diff)
+ diff = described_class.new(gitaly_diff)
- expect(diff.line_count).to eq(9)
+ expect(diff.line_count).to eq(7)
end
end
diff --git a/spec/lib/gitlab/git/gitlab_projects_spec.rb b/spec/lib/gitlab/git/gitlab_projects_spec.rb
deleted file mode 100644
index f5d8503c30c..00000000000
--- a/spec/lib/gitlab/git/gitlab_projects_spec.rb
+++ /dev/null
@@ -1,321 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::GitlabProjects do
- after do
- TestEnv.clean_test_path
- end
-
- around do |example|
- # TODO move this spec to gitaly-ruby. GitlabProjects is not used in gitlab-ce
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- example.run
- end
- end
-
- let(:project) { create(:project, :repository) }
-
- if $VERBOSE
- let(:logger) { Logger.new(STDOUT) }
- else
- let(:logger) { double('logger').as_null_object }
- end
-
- let(:tmp_repos_path) { TestEnv.repos_path }
- let(:repo_name) { project.disk_path + '.git' }
- let(:tmp_repo_path) { File.join(tmp_repos_path, repo_name) }
- let(:gl_projects) { build_gitlab_projects(TestEnv::REPOS_STORAGE, repo_name) }
-
- describe '#initialize' do
- it { expect(gl_projects.shard_path).to eq(tmp_repos_path) }
- it { expect(gl_projects.repository_relative_path).to eq(repo_name) }
- it { expect(gl_projects.repository_absolute_path).to eq(File.join(tmp_repos_path, repo_name)) }
- it { expect(gl_projects.logger).to eq(logger) }
- end
-
- describe '#push_branches' do
- let(:remote_name) { 'remote-name' }
- let(:branch_name) { 'master' }
- let(:cmd) { %W(#{Gitlab.config.git.bin_path} push -- #{remote_name} #{branch_name}) }
- let(:force) { false }
-
- subject { gl_projects.push_branches(remote_name, 600, force, [branch_name]) }
-
- it 'executes the command' do
- stub_spawn(cmd, 600, tmp_repo_path, success: true)
-
- is_expected.to be_truthy
- end
-
- it 'fails' do
- stub_spawn(cmd, 600, tmp_repo_path, success: false)
-
- is_expected.to be_falsy
- end
-
- context 'with --force' do
- let(:cmd) { %W(#{Gitlab.config.git.bin_path} push --force -- #{remote_name} #{branch_name}) }
- let(:force) { true }
-
- it 'executes the command' do
- stub_spawn(cmd, 600, tmp_repo_path, success: true)
-
- is_expected.to be_truthy
- end
- end
- end
-
- describe '#fetch_remote' do
- let(:remote_name) { 'remote-name' }
- let(:branch_name) { 'master' }
- let(:force) { false }
- let(:prune) { true }
- let(:tags) { true }
- let(:args) { { force: force, tags: tags, prune: prune }.merge(extra_args) }
- let(:extra_args) { {} }
- let(:cmd) { %W(#{Gitlab.config.git.bin_path} fetch #{remote_name} --quiet --prune --tags) }
-
- subject { gl_projects.fetch_remote(remote_name, 600, args) }
-
- def stub_tempfile(name, filename, opts = {})
- chmod = opts.delete(:chmod)
- file = StringIO.new
-
- allow(file).to receive(:close!)
- allow(file).to receive(:path).and_return(name)
-
- expect(Tempfile).to receive(:new).with(filename).and_return(file)
- expect(file).to receive(:chmod).with(chmod) if chmod
-
- file
- end
-
- context 'with default args' do
- it 'executes the command' do
- stub_spawn(cmd, 600, tmp_repo_path, {}, success: true)
-
- is_expected.to be_truthy
- end
-
- it 'fails' do
- stub_spawn(cmd, 600, tmp_repo_path, {}, success: false)
-
- is_expected.to be_falsy
- end
- end
-
- context 'with --force' do
- let(:force) { true }
- let(:cmd) { %W(#{Gitlab.config.git.bin_path} fetch #{remote_name} --quiet --prune --force --tags) }
-
- it 'executes the command with forced option' do
- stub_spawn(cmd, 600, tmp_repo_path, {}, success: true)
-
- is_expected.to be_truthy
- end
- end
-
- context 'with --no-tags' do
- let(:tags) { false }
- let(:cmd) { %W(#{Gitlab.config.git.bin_path} fetch #{remote_name} --quiet --prune --no-tags) }
-
- it 'executes the command' do
- stub_spawn(cmd, 600, tmp_repo_path, {}, success: true)
-
- is_expected.to be_truthy
- end
- end
-
- context 'with no prune' do
- let(:prune) { false }
- let(:cmd) { %W(#{Gitlab.config.git.bin_path} fetch #{remote_name} --quiet --tags) }
-
- it 'executes the command' do
- stub_spawn(cmd, 600, tmp_repo_path, {}, success: true)
-
- is_expected.to be_truthy
- end
- end
-
- describe 'with an SSH key' do
- let(:extra_args) { { ssh_key: 'SSH KEY' } }
-
- it 'sets GIT_SSH to a custom script' do
- script = stub_tempfile('scriptFile', 'gitlab-shell-ssh-wrapper', chmod: 0o755)
- key = stub_tempfile('/tmp files/keyFile', 'gitlab-shell-key-file', chmod: 0o400)
-
- stub_spawn(cmd, 600, tmp_repo_path, { 'GIT_SSH' => 'scriptFile' }, success: true)
-
- is_expected.to be_truthy
-
- expect(script.string).to eq("#!/bin/sh\nexec ssh '-oIdentityFile=\"/tmp files/keyFile\"' '-oIdentitiesOnly=\"yes\"' \"$@\"")
- expect(key.string).to eq('SSH KEY')
- end
- end
-
- describe 'with known_hosts data' do
- let(:extra_args) { { known_hosts: 'KNOWN HOSTS' } }
-
- it 'sets GIT_SSH to a custom script' do
- script = stub_tempfile('scriptFile', 'gitlab-shell-ssh-wrapper', chmod: 0o755)
- key = stub_tempfile('/tmp files/knownHosts', 'gitlab-shell-known-hosts', chmod: 0o400)
-
- stub_spawn(cmd, 600, tmp_repo_path, { 'GIT_SSH' => 'scriptFile' }, success: true)
-
- is_expected.to be_truthy
-
- expect(script.string).to eq("#!/bin/sh\nexec ssh '-oStrictHostKeyChecking=\"yes\"' '-oUserKnownHostsFile=\"/tmp files/knownHosts\"' \"$@\"")
- expect(key.string).to eq('KNOWN HOSTS')
- end
- end
- end
-
- describe '#import_project' do
- let(:project) { create(:project) }
- let(:import_url) { TestEnv.factory_repo_path_bare }
- let(:cmd) { %W(#{Gitlab.config.git.bin_path} clone --bare -- #{import_url} #{tmp_repo_path}) }
- let(:timeout) { 600 }
-
- subject { gl_projects.import_project(import_url, timeout) }
-
- shared_examples 'importing repository' do
- context 'success import' do
- it 'imports a repo' do
- expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
-
- is_expected.to be_truthy
-
- expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_truthy
- end
- end
-
- context 'already exists' do
- it "doesn't import" do
- FileUtils.mkdir_p(tmp_repo_path)
-
- is_expected.to be_falsy
- end
- end
- end
-
- describe 'logging' do
- it 'imports a repo' do
- message = "Importing project from <#{import_url}> to <#{tmp_repo_path}>."
- expect(logger).to receive(:info).with(message)
-
- subject
- end
- end
-
- context 'timeout' do
- it 'does not import a repo' do
- stub_spawn_timeout(cmd, timeout, nil)
-
- message = "Importing project from <#{import_url}> to <#{tmp_repo_path}> failed."
- expect(logger).to receive(:error).with(message)
-
- is_expected.to be_falsy
-
- expect(gl_projects.output).to eq("Timed out\n")
- expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
- end
- end
-
- it_behaves_like 'importing repository'
- end
-
- describe '#fork_repository' do
- let(:dest_repos) { TestEnv::REPOS_STORAGE }
- let(:dest_repos_path) { tmp_repos_path }
- let(:dest_repo_name) { File.join('@hashed', 'aa', 'bb', 'xyz.git') }
- let(:dest_repo) { File.join(dest_repos_path, dest_repo_name) }
-
- subject { gl_projects.fork_repository(dest_repos, dest_repo_name) }
-
- before do
- FileUtils.mkdir_p(dest_repos_path)
- end
-
- after do
- FileUtils.rm_rf(dest_repos_path)
- end
-
- shared_examples 'forking a repository' do
- it 'forks the repository' do
- is_expected.to be_truthy
-
- expect(File.exist?(dest_repo)).to be_truthy
- expect(File.exist?(File.join(dest_repo, 'hooks', 'pre-receive'))).to be_truthy
- expect(File.exist?(File.join(dest_repo, 'hooks', 'post-receive'))).to be_truthy
- end
-
- it 'does not fork if a project of the same name already exists' do
- # create a fake project at the intended destination
- FileUtils.mkdir_p(dest_repo)
-
- is_expected.to be_falsy
- end
- end
-
- it_behaves_like 'forking a repository'
-
- # We seem to be stuck to having only one working Gitaly storage in tests, changing
- # that is not very straight-forward so I'm leaving this test here for now till
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/41393 is fixed.
- context 'different storages' do
- let(:dest_repos) { 'alternative' }
- let(:dest_repos_path) { File.join(File.dirname(tmp_repos_path), dest_repos) }
-
- before do
- stub_storage_settings(dest_repos => { 'path' => dest_repos_path })
- end
-
- it 'forks the repo' do
- is_expected.to be_truthy
-
- expect(File.exist?(dest_repo)).to be_truthy
- expect(File.exist?(File.join(dest_repo, 'hooks', 'pre-receive'))).to be_truthy
- expect(File.exist?(File.join(dest_repo, 'hooks', 'post-receive'))).to be_truthy
- end
- end
-
- describe 'log messages' do
- describe 'successful fork' do
- it do
- message = "Forking repository from <#{tmp_repo_path}> to <#{dest_repo}>."
- expect(logger).to receive(:info).with(message)
-
- subject
- end
- end
-
- describe 'failed fork due existing destination' do
- it do
- FileUtils.mkdir_p(dest_repo)
- message = "fork-repository failed: destination repository <#{dest_repo}> already exists."
- expect(logger).to receive(:error).with(message)
-
- subject
- end
- end
- end
- end
-
- def build_gitlab_projects(*args)
- described_class.new(
- *args,
- global_hooks_path: Gitlab.config.gitlab_shell.hooks_path,
- logger: logger
- )
- end
-
- def stub_spawn(*args, success: true)
- exitstatus = success ? 0 : nil
- expect(gl_projects).to receive(:popen_with_timeout).with(*args)
- .and_return(["output", exitstatus])
- end
-
- def stub_spawn_timeout(*args)
- expect(gl_projects).to receive(:popen_with_timeout).with(*args)
- .and_raise(Timeout::Error)
- end
-end
diff --git a/spec/lib/gitlab/git/hook_spec.rb b/spec/lib/gitlab/git/hook_spec.rb
deleted file mode 100644
index a45c8510b15..00000000000
--- a/spec/lib/gitlab/git/hook_spec.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-require 'spec_helper'
-require 'fileutils'
-
-describe Gitlab::Git::Hook do
- before do
- # We need this because in the spec/spec_helper.rb we define it like this:
- # allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil])
- allow_any_instance_of(described_class).to receive(:trigger).and_call_original
- end
-
- around do |example|
- # TODO move hook tests to gitaly-ruby. Hook will disappear from gitlab-ce
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- example.run
- end
- end
-
- describe "#trigger" do
- set(:project) { create(:project, :repository) }
- let(:repository) { project.repository.raw_repository }
- let(:repo_path) { repository.path }
- let(:hooks_dir) { File.join(repo_path, 'hooks') }
- let(:user) { create(:user) }
- let(:gl_id) { Gitlab::GlId.gl_id(user) }
- let(:gl_username) { user.username }
-
- def create_hook(name)
- FileUtils.mkdir_p(hooks_dir)
- hook_path = File.join(hooks_dir, name)
- File.open(hook_path, 'w', 0755) do |f|
- f.write(<<~HOOK)
- #!/bin/sh
- exit 0
- HOOK
- end
- end
-
- def create_failing_hook(name)
- FileUtils.mkdir_p(hooks_dir)
- hook_path = File.join(hooks_dir, name)
- File.open(hook_path, 'w', 0755) do |f|
- f.write(<<~HOOK)
- #!/bin/sh
- echo 'regular message from the hook'
- echo 'error message from the hook' 1>&2
- echo 'error message from the hook line 2' 1>&2
- exit 1
- HOOK
- end
- end
-
- ['pre-receive', 'post-receive', 'update'].each do |hook_name|
- context "when triggering a #{hook_name} hook" do
- context "when the hook is successful" do
- let(:hook_path) { File.join(hooks_dir, hook_name) }
- let(:gl_repository) { Gitlab::GlRepository.gl_repository(project, false) }
- let(:env) do
- {
- 'GL_ID' => gl_id,
- 'GL_USERNAME' => gl_username,
- 'PWD' => repo_path,
- 'GL_PROTOCOL' => 'web',
- 'GL_REPOSITORY' => gl_repository
- }
- end
-
- it "returns success with no errors" do
- create_hook(hook_name)
- hook = described_class.new(hook_name, repository)
- blank = Gitlab::Git::BLANK_SHA
- ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
-
- if hook_name != 'update'
- expect(Open3).to receive(:popen3)
- .with(env, hook_path, chdir: repo_path).and_call_original
- end
-
- status, errors = hook.trigger(gl_id, gl_username, blank, blank, ref)
- expect(status).to be true
- expect(errors).to be_blank
- end
- end
-
- context "when the hook is unsuccessful" do
- it "returns failure with errors" do
- create_failing_hook(hook_name)
- hook = described_class.new(hook_name, repository)
- blank = Gitlab::Git::BLANK_SHA
- ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
-
- status, errors = hook.trigger(gl_id, gl_username, blank, blank, ref)
- expect(status).to be false
- expect(errors).to eq("error message from the hook\nerror message from the hook line 2\n")
- end
- end
- end
- end
-
- context "when the hook doesn't exist" do
- it "returns success with no errors" do
- hook = described_class.new('unknown_hook', repository)
- blank = Gitlab::Git::BLANK_SHA
- ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
-
- status, errors = hook.trigger(gl_id, gl_username, blank, blank, ref)
- expect(status).to be true
- expect(errors).to be_nil
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/git/hooks_service_spec.rb b/spec/lib/gitlab/git/hooks_service_spec.rb
deleted file mode 100644
index 55ffced36ac..00000000000
--- a/spec/lib/gitlab/git/hooks_service_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::HooksService, :seed_helper do
- let(:gl_id) { 'user-456' }
- let(:gl_username) { 'janedoe' }
- let(:user) { Gitlab::Git::User.new(gl_username, 'Jane Doe', 'janedoe@example.com', gl_id) }
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, 'project-123') }
- let(:service) { described_class.new }
- let(:blankrev) { Gitlab::Git::BLANK_SHA }
- let(:oldrev) { SeedRepo::Commit::PARENT_ID }
- let(:newrev) { SeedRepo::Commit::ID }
- let(:ref) { 'refs/heads/feature' }
-
- describe '#execute' do
- context 'when receive hooks were successful' do
- let(:hook) { double(:hook) }
-
- it 'calls all three hooks' do
- expect(Gitlab::Git::Hook).to receive(:new).exactly(3).times.and_return(hook)
- expect(hook).to receive(:trigger).with(gl_id, gl_username, blankrev, newrev, ref)
- .exactly(3).times.and_return([true, nil])
-
- service.execute(user, repository, blankrev, newrev, ref) { }
- end
- end
-
- context 'when pre-receive hook failed' do
- it 'does not call post-receive hook' do
- expect(service).to receive(:run_hook).with('pre-receive').and_return([false, 'hello world'])
- expect(service).not_to receive(:run_hook).with('post-receive')
-
- expect do
- service.execute(user, repository, blankrev, newrev, ref)
- end.to raise_error(Gitlab::Git::PreReceiveError, 'hello world')
- end
- end
-
- context 'when update hook failed' do
- it 'does not call post-receive hook' do
- expect(service).to receive(:run_hook).with('pre-receive').and_return([true, nil])
- expect(service).to receive(:run_hook).with('update').and_return([false, 'hello world'])
- expect(service).not_to receive(:run_hook).with('post-receive')
-
- expect do
- service.execute(user, repository, blankrev, newrev, ref)
- end.to raise_error(Gitlab::Git::PreReceiveError, 'hello world')
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/git/index_spec.rb b/spec/lib/gitlab/git/index_spec.rb
deleted file mode 100644
index c4edd6961e1..00000000000
--- a/spec/lib/gitlab/git/index_spec.rb
+++ /dev/null
@@ -1,239 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Index, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
- let(:index) { described_class.new(repository) }
-
- before do
- index.read_tree(lookup('master').tree)
- end
-
- around do |example|
- # TODO move these specs to gitaly-ruby. The Index class will disappear from gitlab-ce
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- example.run
- end
- end
-
- describe '#create' do
- let(:options) do
- {
- content: 'Lorem ipsum...',
- file_path: 'documents/story.txt'
- }
- end
-
- context 'when no file at that path exists' do
- it 'creates the file in the index' do
- index.create(options)
-
- entry = index.get(options[:file_path])
-
- expect(entry).not_to be_nil
- expect(lookup(entry[:oid]).content).to eq(options[:content])
- end
- end
-
- context 'when a file at that path exists' do
- before do
- options[:file_path] = 'files/executables/ls'
- end
-
- it 'raises an error' do
- expect { index.create(options) }.to raise_error('A file with this name already exists')
- end
- end
-
- context 'when content is in base64' do
- before do
- options[:content] = Base64.encode64(options[:content])
- options[:encoding] = 'base64'
- end
-
- it 'decodes base64' do
- index.create(options)
-
- entry = index.get(options[:file_path])
- expect(lookup(entry[:oid]).content).to eq(Base64.decode64(options[:content]))
- end
- end
-
- context 'when content contains CRLF' do
- before do
- repository.autocrlf = :input
- options[:content] = "Hello,\r\nWorld"
- end
-
- it 'converts to LF' do
- index.create(options)
-
- entry = index.get(options[:file_path])
- expect(lookup(entry[:oid]).content).to eq("Hello,\nWorld")
- end
- end
- end
-
- describe '#create_dir' do
- let(:options) do
- {
- file_path: 'newdir'
- }
- end
-
- context 'when no file or dir at that path exists' do
- it 'creates the dir in the index' do
- index.create_dir(options)
-
- entry = index.get(options[:file_path] + '/.gitkeep')
-
- expect(entry).not_to be_nil
- end
- end
-
- context 'when a file at that path exists' do
- before do
- options[:file_path] = 'files/executables/ls'
- end
-
- it 'raises an error' do
- expect { index.create_dir(options) }.to raise_error('A file with this name already exists')
- end
- end
-
- context 'when a directory at that path exists' do
- before do
- options[:file_path] = 'files/executables'
- end
-
- it 'raises an error' do
- expect { index.create_dir(options) }.to raise_error('A directory with this name already exists')
- end
- end
- end
-
- describe '#update' do
- let(:options) do
- {
- content: 'Lorem ipsum...',
- file_path: 'README.md'
- }
- end
-
- context 'when no file at that path exists' do
- before do
- options[:file_path] = 'documents/story.txt'
- end
-
- it 'raises an error' do
- expect { index.update(options) }.to raise_error("A file with this name doesn't exist")
- end
- end
-
- context 'when a file at that path exists' do
- it 'updates the file in the index' do
- index.update(options)
-
- entry = index.get(options[:file_path])
-
- expect(lookup(entry[:oid]).content).to eq(options[:content])
- end
-
- it 'preserves file mode' do
- options[:file_path] = 'files/executables/ls'
-
- index.update(options)
-
- entry = index.get(options[:file_path])
-
- expect(entry[:mode]).to eq(0100755)
- end
- end
- end
-
- describe '#move' do
- let(:options) do
- {
- content: 'Lorem ipsum...',
- previous_path: 'README.md',
- file_path: 'NEWREADME.md'
- }
- end
-
- context 'when no file at that path exists' do
- it 'raises an error' do
- options[:previous_path] = 'documents/story.txt'
-
- expect { index.move(options) }.to raise_error("A file with this name doesn't exist")
- end
- end
-
- context 'when a file at the new path already exists' do
- it 'raises an error' do
- options[:file_path] = 'CHANGELOG'
-
- expect { index.move(options) }.to raise_error("A file with this name already exists")
- end
- end
-
- context 'when a file at that path exists' do
- it 'removes the old file in the index' do
- index.move(options)
-
- entry = index.get(options[:previous_path])
-
- expect(entry).to be_nil
- end
-
- it 'creates the new file in the index' do
- index.move(options)
-
- entry = index.get(options[:file_path])
-
- expect(entry).not_to be_nil
- expect(lookup(entry[:oid]).content).to eq(options[:content])
- end
-
- it 'preserves file mode' do
- options[:previous_path] = 'files/executables/ls'
-
- index.move(options)
-
- entry = index.get(options[:file_path])
-
- expect(entry[:mode]).to eq(0100755)
- end
- end
- end
-
- describe '#delete' do
- let(:options) do
- {
- file_path: 'README.md'
- }
- end
-
- context 'when no file at that path exists' do
- before do
- options[:file_path] = 'documents/story.txt'
- end
-
- it 'raises an error' do
- expect { index.delete(options) }.to raise_error("A file with this name doesn't exist")
- end
- end
-
- context 'when a file at that path exists' do
- it 'removes the file in the index' do
- index.delete(options)
-
- entry = index.get(options[:file_path])
-
- expect(entry).to be_nil
- end
- end
- end
-
- def lookup(revision)
- repository.rugged.rev_parse(revision)
- end
-end
diff --git a/spec/lib/gitlab/git/popen_spec.rb b/spec/lib/gitlab/git/popen_spec.rb
deleted file mode 100644
index 074e66d2a5d..00000000000
--- a/spec/lib/gitlab/git/popen_spec.rb
+++ /dev/null
@@ -1,179 +0,0 @@
-require 'spec_helper'
-
-describe 'Gitlab::Git::Popen' do
- let(:path) { Rails.root.join('tmp').to_s }
- let(:test_string) { 'The quick brown fox jumped over the lazy dog' }
- # The pipe buffer is typically 64K. This string is about 440K.
- let(:spew_command) { ['bash', '-c', "for i in {1..10000}; do echo '#{test_string}' 1>&2; done"] }
-
- let(:klass) do
- Class.new(Object) do
- include Gitlab::Git::Popen
- end
- end
-
- context 'popen' do
- context 'zero status' do
- let(:result) { klass.new.popen(%w(ls), path) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to be_zero }
- it { expect(output).to include('tests') }
- end
-
- context 'non-zero status' do
- let(:result) { klass.new.popen(%w(cat NOTHING), path) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to eq(1) }
- it { expect(output).to include('No such file or directory') }
- end
-
- context 'unsafe string command' do
- it 'raises an error when it gets called with a string argument' do
- expect { klass.new.popen('ls', path) }.to raise_error(RuntimeError)
- end
- end
-
- context 'with custom options' do
- let(:vars) { { 'foobar' => 123, 'PWD' => path } }
- let(:options) { { chdir: path } }
-
- it 'calls popen3 with the provided environment variables' do
- expect(Open3).to receive(:popen3).with(vars, 'ls', options)
-
- klass.new.popen(%w(ls), path, { 'foobar' => 123 })
- end
- end
-
- context 'use stdin' do
- let(:result) { klass.new.popen(%w[cat], path) { |stdin| stdin.write 'hello' } }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to be_zero }
- it { expect(output).to eq('hello') }
- end
-
- context 'with lazy block' do
- it 'yields a lazy io' do
- expect_lazy_io = lambda do |io|
- expect(io).to be_a Enumerator::Lazy
- expect(io.inspect).to include('#<IO:fd')
- end
-
- klass.new.popen(%w[ls], path, lazy_block: expect_lazy_io)
- end
-
- it "doesn't wait for process exit" do
- Timeout.timeout(2) do
- klass.new.popen(%w[yes], path, lazy_block: ->(io) {})
- end
- end
- end
-
- context 'with a process that writes a lot of data to stderr' do
- it 'returns zero' do
- output, status = klass.new.popen(spew_command, path)
-
- expect(output).to include(test_string)
- expect(status).to eq(0)
- end
- end
- end
-
- context 'popen_with_timeout' do
- let(:timeout) { 1.second }
-
- context 'no timeout' do
- context 'zero status' do
- let(:result) { klass.new.popen_with_timeout(%w(ls), timeout, path) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to be_zero }
- it { expect(output).to include('tests') }
- end
-
- context 'multi-line string' do
- let(:test_string) { "this is 1 line\n2nd line\n3rd line\n" }
- let(:result) { klass.new.popen_with_timeout(['echo', test_string], timeout, path) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to be_zero }
- # echo adds its own line
- it { expect(output).to eq(test_string + "\n") }
- end
-
- context 'non-zero status' do
- let(:result) { klass.new.popen_with_timeout(%w(cat NOTHING), timeout, path) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to eq(1) }
- it { expect(output).to include('No such file or directory') }
- end
-
- context 'unsafe string command' do
- it 'raises an error when it gets called with a string argument' do
- expect { klass.new.popen_with_timeout('ls', timeout, path) }.to raise_error(RuntimeError)
- end
- end
- end
-
- context 'timeout' do
- context 'timeout' do
- it "raises a Timeout::Error" do
- expect { klass.new.popen_with_timeout(%w(sleep 1000), timeout, path) }.to raise_error(Timeout::Error)
- end
-
- it "handles processes that do not shutdown correctly" do
- expect { klass.new.popen_with_timeout(['bash', '-c', "trap -- '' SIGTERM; sleep 1000"], timeout, path) }.to raise_error(Timeout::Error)
- end
-
- it 'handles process that writes a lot of data to stderr' do
- output, status = klass.new.popen_with_timeout(spew_command, timeout, path)
-
- expect(output).to include(test_string)
- expect(status).to eq(0)
- end
- end
-
- context 'timeout period' do
- let(:time_taken) do
- begin
- start = Time.now
- klass.new.popen_with_timeout(%w(sleep 1000), timeout, path)
- rescue
- Time.now - start
- end
- end
-
- it { expect(time_taken).to be >= timeout }
- end
-
- context 'clean up' do
- let(:instance) { klass.new }
-
- it 'kills the child process' do
- expect(instance).to receive(:kill_process_group_for_pid).and_wrap_original do |m, *args|
- # is the PID, and it should not be running at this point
- m.call(*args)
-
- pid = args.first
- begin
- Process.getpgid(pid)
- raise "The child process should have been killed"
- rescue Errno::ESRCH
- end
- end
-
- expect { instance.popen_with_timeout(['bash', '-c', "trap -- '' SIGTERM; sleep 1000"], timeout, path) }.to raise_error(Timeout::Error)
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 17348b01006..dfe36d7d459 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -322,21 +322,12 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#commit_count' do
- shared_examples 'simple commit counting' do
- it { expect(repository.commit_count("master")).to eq(25) }
- it { expect(repository.commit_count("feature")).to eq(9) }
- it { expect(repository.commit_count("does-not-exist")).to eq(0) }
- end
-
- context 'when Gitaly commit_count feature is enabled' do
- it_behaves_like 'simple commit counting'
- it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::CommitService, :commit_count do
- subject { repository.commit_count('master') }
- end
- end
+ it { expect(repository.commit_count("master")).to eq(25) }
+ it { expect(repository.commit_count("feature")).to eq(9) }
+ it { expect(repository.commit_count("does-not-exist")).to eq(0) }
- context 'when Gitaly commit_count feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'simple commit counting'
+ it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::CommitService, :commit_count do
+ subject { repository.commit_count('master') }
end
end
@@ -378,118 +369,88 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe "#delete_branch" do
- shared_examples "deleting a branch" do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
-
- after do
- ensure_seeds
- end
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
- it "removes the branch from the repo" do
- branch_name = "to-be-deleted-soon"
+ after do
+ ensure_seeds
+ end
- repository.create_branch(branch_name)
- expect(repository_rugged.branches[branch_name]).not_to be_nil
+ it "removes the branch from the repo" do
+ branch_name = "to-be-deleted-soon"
- repository.delete_branch(branch_name)
- expect(repository_rugged.branches[branch_name]).to be_nil
- end
+ repository.create_branch(branch_name)
+ expect(repository_rugged.branches[branch_name]).not_to be_nil
- context "when branch does not exist" do
- it "raises a DeleteBranchError exception" do
- expect { repository.delete_branch("this-branch-does-not-exist") }.to raise_error(Gitlab::Git::Repository::DeleteBranchError)
- end
- end
+ repository.delete_branch(branch_name)
+ expect(repository_rugged.branches[branch_name]).to be_nil
end
- context "when Gitaly delete_branch is enabled" do
- it_behaves_like "deleting a branch"
- end
-
- context "when Gitaly delete_branch is disabled", :skip_gitaly_mock do
- it_behaves_like "deleting a branch"
+ context "when branch does not exist" do
+ it "raises a DeleteBranchError exception" do
+ expect { repository.delete_branch("this-branch-does-not-exist") }.to raise_error(Gitlab::Git::Repository::DeleteBranchError)
+ end
end
end
describe "#create_branch" do
- shared_examples 'creating a branch' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
-
- after do
- ensure_seeds
- end
-
- it "should create a new branch" do
- expect(repository.create_branch('new_branch', 'master')).not_to be_nil
- end
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
- it "should create a new branch with the right name" do
- expect(repository.create_branch('another_branch', 'master').name).to eq('another_branch')
- end
+ after do
+ ensure_seeds
+ end
- it "should fail if we create an existing branch" do
- repository.create_branch('duplicated_branch', 'master')
- expect {repository.create_branch('duplicated_branch', 'master')}.to raise_error("Branch duplicated_branch already exists")
- end
+ it "should create a new branch" do
+ expect(repository.create_branch('new_branch', 'master')).not_to be_nil
+ end
- it "should fail if we create a branch from a non existing ref" do
- expect {repository.create_branch('branch_based_in_wrong_ref', 'master_2_the_revenge')}.to raise_error("Invalid reference master_2_the_revenge")
- end
+ it "should create a new branch with the right name" do
+ expect(repository.create_branch('another_branch', 'master').name).to eq('another_branch')
end
- context 'when Gitaly create_branch feature is enabled' do
- it_behaves_like 'creating a branch'
+ it "should fail if we create an existing branch" do
+ repository.create_branch('duplicated_branch', 'master')
+ expect {repository.create_branch('duplicated_branch', 'master')}.to raise_error("Branch duplicated_branch already exists")
end
- context 'when Gitaly create_branch feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'creating a branch'
+ it "should fail if we create a branch from a non existing ref" do
+ expect {repository.create_branch('branch_based_in_wrong_ref', 'master_2_the_revenge')}.to raise_error("Invalid reference master_2_the_revenge")
end
end
describe '#delete_refs' do
- shared_examples 'deleting refs' do
- let(:repo) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
-
- def repo_rugged
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repo.rugged
- end
- end
+ let(:repo) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
- after do
- ensure_seeds
+ def repo_rugged
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ repo.rugged
end
+ end
- it 'deletes the ref' do
- repo.delete_refs('refs/heads/feature')
+ after do
+ ensure_seeds
+ end
- expect(repo_rugged.references['refs/heads/feature']).to be_nil
- end
+ it 'deletes the ref' do
+ repo.delete_refs('refs/heads/feature')
- it 'deletes all refs' do
- refs = %w[refs/heads/wip refs/tags/v1.1.0]
- repo.delete_refs(*refs)
+ expect(repo_rugged.references['refs/heads/feature']).to be_nil
+ end
- refs.each do |ref|
- expect(repo_rugged.references[ref]).to be_nil
- end
- end
+ it 'deletes all refs' do
+ refs = %w[refs/heads/wip refs/tags/v1.1.0]
+ repo.delete_refs(*refs)
- it 'does not fail when deleting an empty list of refs' do
- expect { repo.delete_refs(*[]) }.not_to raise_error
- end
-
- it 'raises an error if it failed' do
- expect { repo.delete_refs('refs\heads\fix') }.to raise_error(Gitlab::Git::Repository::GitError)
+ refs.each do |ref|
+ expect(repo_rugged.references[ref]).to be_nil
end
end
- context 'when Gitaly delete_refs feature is enabled' do
- it_behaves_like 'deleting refs'
+ it 'does not fail when deleting an empty list of refs' do
+ expect { repo.delete_refs(*[]) }.not_to raise_error
end
- context 'when Gitaly delete_refs feature is disabled', :disable_gitaly do
- it_behaves_like 'deleting refs'
+ it 'raises an error if it failed' do
+ expect { repo.delete_refs('refs\heads\fix') }.to raise_error(Gitlab::Git::Repository::GitError)
end
end
@@ -542,44 +503,65 @@ describe Gitlab::Git::Repository, :seed_helper do
Gitlab::Shell.new.remove_repository('default', 'my_project')
end
- shared_examples 'repository mirror fetching' do
- it 'fetches a repository as a mirror remote' do
+ it 'fetches a repository as a mirror remote' do
+ subject
+
+ expect(refs(new_repository_path)).to eq(refs(repository_path))
+ end
+
+ context 'with keep-around refs' do
+ let(:sha) { SeedRepo::Commit::ID }
+ let(:keep_around_ref) { "refs/keep-around/#{sha}" }
+ let(:tmp_ref) { "refs/tmp/#{SecureRandom.hex}" }
+
+ before do
+ repository_rugged.references.create(keep_around_ref, sha, force: true)
+ repository_rugged.references.create(tmp_ref, sha, force: true)
+ end
+
+ it 'includes the temporary and keep-around refs' do
subject
- expect(refs(new_repository_path)).to eq(refs(repository_path))
+ expect(refs(new_repository_path)).to include(keep_around_ref)
+ expect(refs(new_repository_path)).to include(tmp_ref)
end
+ end
- context 'with keep-around refs' do
- let(:sha) { SeedRepo::Commit::ID }
- let(:keep_around_ref) { "refs/keep-around/#{sha}" }
- let(:tmp_ref) { "refs/tmp/#{SecureRandom.hex}" }
+ def new_repository_path
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ new_repository.path
+ end
+ end
+ end
- before do
- repository_rugged.references.create(keep_around_ref, sha, force: true)
- repository_rugged.references.create(tmp_ref, sha, force: true)
- end
+ describe '#find_remote_root_ref' do
+ it 'gets the remote root ref from GitalyClient' do
+ expect_any_instance_of(Gitlab::GitalyClient::RemoteService)
+ .to receive(:find_remote_root_ref).and_call_original
- it 'includes the temporary and keep-around refs' do
- subject
+ expect(repository.find_remote_root_ref('origin')).to eq 'master'
+ end
- expect(refs(new_repository_path)).to include(keep_around_ref)
- expect(refs(new_repository_path)).to include(tmp_ref)
- end
- end
+ it 'returns UTF-8' do
+ expect(repository.find_remote_root_ref('origin')).to be_utf8
end
- context 'with gitaly enabled' do
- it_behaves_like 'repository mirror fetching'
+ it 'returns nil when remote name is nil' do
+ expect_any_instance_of(Gitlab::GitalyClient::RemoteService)
+ .not_to receive(:find_remote_root_ref)
+
+ expect(repository.find_remote_root_ref(nil)).to be_nil
end
- context 'with gitaly enabled', :skip_gitaly_mock do
- it_behaves_like 'repository mirror fetching'
+ it 'returns nil when remote name is empty' do
+ expect_any_instance_of(Gitlab::GitalyClient::RemoteService)
+ .not_to receive(:find_remote_root_ref)
+
+ expect(repository.find_remote_root_ref('')).to be_nil
end
- def new_repository_path
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- new_repository.path
- end
+ it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RemoteService, :find_remote_root_ref do
+ subject { repository.find_remote_root_ref('origin') }
end
end
@@ -887,25 +869,15 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#merge_base' do
- shared_examples '#merge_base' do
- where(:from, :to, :result) do
- '570e7b2abdd848b95f2f578043fc23bd6f6fd24d' | '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d'
- '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d'
- '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | 'foobar' | nil
- 'foobar' | '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | nil
- end
-
- with_them do
- it { expect(repository.merge_base(from, to)).to eq(result) }
- end
- end
-
- context 'with gitaly' do
- it_behaves_like '#merge_base'
+ where(:from, :to, :result) do
+ '570e7b2abdd848b95f2f578043fc23bd6f6fd24d' | '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d'
+ '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d'
+ '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | 'foobar' | nil
+ 'foobar' | '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | nil
end
- context 'without gitaly', :skip_gitaly_mock do
- it_behaves_like '#merge_base'
+ with_them do
+ it { expect(repository.merge_base(from, to)).to eq(result) }
end
end
@@ -997,54 +969,6 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
- describe '#autocrlf' do
- before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- @repo.rugged.config['core.autocrlf'] = true
- end
-
- around do |example|
- # OK because autocrlf is only used in gitaly-ruby
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- example.run
- end
- end
-
- it 'return the value of the autocrlf option' do
- expect(@repo.autocrlf).to be(true)
- end
-
- after(:all) do
- @repo.rugged.config.delete('core.autocrlf')
- end
- end
-
- describe '#autocrlf=' do
- before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- @repo.rugged.config['core.autocrlf'] = false
- end
-
- around do |example|
- # OK because autocrlf= is only used in gitaly-ruby
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- example.run
- end
- end
-
- it 'should set the autocrlf option to the provided option' do
- @repo.autocrlf = :input
-
- File.open(File.join(SEED_STORAGE_PATH, TEST_MUTABLE_REPO_PATH, 'config')) do |config_file|
- expect(config_file.read).to match('autocrlf = input')
- end
- end
-
- after(:all) do
- @repo.rugged.config.delete('core.autocrlf')
- end
- end
-
describe '#find_branch' do
it 'should return a Branch for master' do
branch = repository.find_branch('master')
@@ -1144,57 +1068,47 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#merged_branch_names' do
- shared_examples 'finding merged branch names' do
- context 'when branch names are passed' do
- it 'only returns the names we are asking' do
- names = repository.merged_branch_names(%w[merge-test])
+ context 'when branch names are passed' do
+ it 'only returns the names we are asking' do
+ names = repository.merged_branch_names(%w[merge-test])
- expect(names).to contain_exactly('merge-test')
- end
+ expect(names).to contain_exactly('merge-test')
+ end
- it 'does not return unmerged branch names' do
- names = repository.merged_branch_names(%w[feature])
+ it 'does not return unmerged branch names' do
+ names = repository.merged_branch_names(%w[feature])
- expect(names).to be_empty
- end
+ expect(names).to be_empty
end
+ end
- context 'when no root ref is available' do
- it 'returns empty list' do
- project = create(:project, :empty_repo)
+ context 'when no root ref is available' do
+ it 'returns empty list' do
+ project = create(:project, :empty_repo)
- names = project.repository.merged_branch_names(%w[feature])
+ names = project.repository.merged_branch_names(%w[feature])
- expect(names).to be_empty
- end
+ expect(names).to be_empty
end
+ end
- context 'when no branch names are specified' do
- before do
- repository.create_branch('identical', 'master')
- end
-
- after do
- ensure_seeds
- end
-
- it 'returns all merged branch names except for identical one' do
- names = repository.merged_branch_names
+ context 'when no branch names are specified' do
+ before do
+ repository.create_branch('identical', 'master')
+ end
- expect(names).to include('merge-test')
- expect(names).to include('fix-mode')
- expect(names).not_to include('feature')
- expect(names).not_to include('identical')
- end
+ after do
+ ensure_seeds
end
- end
- context 'when Gitaly merged_branch_names feature is enabled' do
- it_behaves_like 'finding merged branch names'
- end
+ it 'returns all merged branch names except for identical one' do
+ names = repository.merged_branch_names
- context 'when Gitaly merged_branch_names feature is disabled', :disable_gitaly do
- it_behaves_like 'finding merged branch names'
+ expect(names).to include('merge-test')
+ expect(names).to include('fix-mode')
+ expect(names).not_to include('feature')
+ expect(names).not_to include('identical')
+ end
end
end
@@ -1311,76 +1225,46 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#ref_exists?' do
- shared_examples 'checks the existence of refs' do
- it 'returns true for an existing tag' do
- expect(repository.ref_exists?('refs/heads/master')).to eq(true)
- end
-
- it 'returns false for a non-existing tag' do
- expect(repository.ref_exists?('refs/tags/THIS_TAG_DOES_NOT_EXIST')).to eq(false)
- end
-
- it 'raises an ArgumentError for an empty string' do
- expect { repository.ref_exists?('') }.to raise_error(ArgumentError)
- end
+ it 'returns true for an existing tag' do
+ expect(repository.ref_exists?('refs/heads/master')).to eq(true)
+ end
- it 'raises an ArgumentError for an invalid ref' do
- expect { repository.ref_exists?('INVALID') }.to raise_error(ArgumentError)
- end
+ it 'returns false for a non-existing tag' do
+ expect(repository.ref_exists?('refs/tags/THIS_TAG_DOES_NOT_EXIST')).to eq(false)
end
- context 'when Gitaly ref_exists feature is enabled' do
- it_behaves_like 'checks the existence of refs'
+ it 'raises an ArgumentError for an empty string' do
+ expect { repository.ref_exists?('') }.to raise_error(ArgumentError)
end
- context 'when Gitaly ref_exists feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'checks the existence of refs'
+ it 'raises an ArgumentError for an invalid ref' do
+ expect { repository.ref_exists?('INVALID') }.to raise_error(ArgumentError)
end
end
describe '#tag_exists?' do
- shared_examples 'checks the existence of tags' do
- it 'returns true for an existing tag' do
- tag = repository.tag_names.first
+ it 'returns true for an existing tag' do
+ tag = repository.tag_names.first
- expect(repository.tag_exists?(tag)).to eq(true)
- end
-
- it 'returns false for a non-existing tag' do
- expect(repository.tag_exists?('v9000')).to eq(false)
- end
- end
-
- context 'when Gitaly ref_exists_tags feature is enabled' do
- it_behaves_like 'checks the existence of tags'
+ expect(repository.tag_exists?(tag)).to eq(true)
end
- context 'when Gitaly ref_exists_tags feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'checks the existence of tags'
+ it 'returns false for a non-existing tag' do
+ expect(repository.tag_exists?('v9000')).to eq(false)
end
end
describe '#branch_exists?' do
- shared_examples 'checks the existence of branches' do
- it 'returns true for an existing branch' do
- expect(repository.branch_exists?('master')).to eq(true)
- end
-
- it 'returns false for a non-existing branch' do
- expect(repository.branch_exists?('kittens')).to eq(false)
- end
-
- it 'returns false when using an invalid branch name' do
- expect(repository.branch_exists?('.bla')).to eq(false)
- end
+ it 'returns true for an existing branch' do
+ expect(repository.branch_exists?('master')).to eq(true)
end
- context 'when Gitaly ref_exists_branches feature is enabled' do
- it_behaves_like 'checks the existence of branches'
+ it 'returns false for a non-existing branch' do
+ expect(repository.branch_exists?('kittens')).to eq(false)
end
- context 'when Gitaly ref_exists_branches feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'checks the existence of branches'
+ it 'returns false when using an invalid branch name' do
+ expect(repository.branch_exists?('.bla')).to eq(false)
end
end
@@ -1471,52 +1355,6 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
- describe '#with_repo_branch_commit' do
- context 'when comparing with the same repository' do
- let(:start_repository) { repository }
-
- context 'when the branch exists' do
- let(:start_branch_name) { 'master' }
-
- it 'yields the commit' do
- expect { |b| repository.with_repo_branch_commit(start_repository, start_branch_name, &b) }
- .to yield_with_args(an_instance_of(Gitlab::Git::Commit))
- end
- end
-
- context 'when the branch does not exist' do
- let(:start_branch_name) { 'definitely-not-master' }
-
- it 'yields nil' do
- expect { |b| repository.with_repo_branch_commit(start_repository, start_branch_name, &b) }
- .to yield_with_args(nil)
- end
- end
- end
-
- context 'when comparing with another repository' do
- let(:start_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
-
- context 'when the branch exists' do
- let(:start_branch_name) { 'master' }
-
- it 'yields the commit' do
- expect { |b| repository.with_repo_branch_commit(start_repository, start_branch_name, &b) }
- .to yield_with_args(an_instance_of(Gitlab::Git::Commit))
- end
- end
-
- context 'when the branch does not exist' do
- let(:start_branch_name) { 'definitely-not-master' }
-
- it 'yields nil' do
- expect { |b| repository.with_repo_branch_commit(start_repository, start_branch_name, &b) }
- .to yield_with_args(nil)
- end
- end
- end
- end
-
describe '#fetch_source_branch!' do
let(:local_ref) { 'refs/merge-requests/1/head' }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
@@ -1567,29 +1405,19 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#rm_branch' do
- shared_examples "user deleting a branch" do
- let(:project) { create(:project, :repository) }
- let(:repository) { project.repository.raw }
- let(:branch_name) { "to-be-deleted-soon" }
-
- before do
- project.add_developer(user)
- repository.create_branch(branch_name)
- end
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository.raw }
+ let(:branch_name) { "to-be-deleted-soon" }
- it "removes the branch from the repo" do
- repository.rm_branch(branch_name, user: user)
-
- expect(repository_rugged.branches[branch_name]).to be_nil
- end
+ before do
+ project.add_developer(user)
+ repository.create_branch(branch_name)
end
- context "when Gitaly user_delete_branch is enabled" do
- it_behaves_like "user deleting a branch"
- end
+ it "removes the branch from the repo" do
+ repository.rm_branch(branch_name, user: user)
- context "when Gitaly user_delete_branch is disabled", :skip_gitaly_mock do
- it_behaves_like "user deleting a branch"
+ expect(repository_rugged.branches[branch_name]).to be_nil
end
end
@@ -1713,39 +1541,29 @@ describe Gitlab::Git::Repository, :seed_helper do
ensure_seeds
end
- shared_examples '#merge' do
- it 'can perform a merge' do
- merge_commit_id = nil
- result = repository.merge(user, source_sha, target_branch, 'Test merge') do |commit_id|
- merge_commit_id = commit_id
- end
-
- expect(result.newrev).to eq(merge_commit_id)
- expect(result.repo_created).to eq(false)
- expect(result.branch_created).to eq(false)
+ it 'can perform a merge' do
+ merge_commit_id = nil
+ result = repository.merge(user, source_sha, target_branch, 'Test merge') do |commit_id|
+ merge_commit_id = commit_id
end
- it 'returns nil if there was a concurrent branch update' do
- concurrent_update_id = '33f3729a45c02fc67d00adb1b8bca394b0e761d9'
- result = repository.merge(user, source_sha, target_branch, 'Test merge') do
- # This ref update should make the merge fail
- repository.write_ref(Gitlab::Git::BRANCH_REF_PREFIX + target_branch, concurrent_update_id)
- end
-
- # This 'nil' signals that the merge was not applied
- expect(result).to be_nil
+ expect(result.newrev).to eq(merge_commit_id)
+ expect(result.repo_created).to eq(false)
+ expect(result.branch_created).to eq(false)
+ end
- # Our concurrent ref update should not have been undone
- expect(repository.find_branch(target_branch).target).to eq(concurrent_update_id)
+ it 'returns nil if there was a concurrent branch update' do
+ concurrent_update_id = '33f3729a45c02fc67d00adb1b8bca394b0e761d9'
+ result = repository.merge(user, source_sha, target_branch, 'Test merge') do
+ # This ref update should make the merge fail
+ repository.write_ref(Gitlab::Git::BRANCH_REF_PREFIX + target_branch, concurrent_update_id)
end
- end
- context 'with gitaly' do
- it_behaves_like '#merge'
- end
+ # This 'nil' signals that the merge was not applied
+ expect(result).to be_nil
- context 'without gitaly', :skip_gitaly_mock do
- it_behaves_like '#merge'
+ # Our concurrent ref update should not have been undone
+ expect(repository.find_branch(target_branch).target).to eq(concurrent_update_id)
end
end
@@ -1857,88 +1675,47 @@ describe Gitlab::Git::Repository, :seed_helper do
describe '#add_remote' do
let(:mirror_refmap) { '+refs/*:refs/*' }
- shared_examples 'add_remote' do
- it 'added the remote' do
- begin
- rugged.remotes.delete(remote_name)
- rescue Rugged::ConfigError
- end
-
- repository.add_remote(remote_name, url, mirror_refmap: mirror_refmap)
-
- expect(rugged.remotes[remote_name]).not_to be_nil
- expect(rugged.config["remote.#{remote_name}.mirror"]).to eq('true')
- expect(rugged.config["remote.#{remote_name}.prune"]).to eq('true')
- expect(rugged.config["remote.#{remote_name}.fetch"]).to eq(mirror_refmap)
+ it 'added the remote' do
+ begin
+ rugged.remotes.delete(remote_name)
+ rescue Rugged::ConfigError
end
- end
- context 'using Gitaly' do
- it_behaves_like 'add_remote'
- end
+ repository.add_remote(remote_name, url, mirror_refmap: mirror_refmap)
- context 'with Gitaly disabled', :disable_gitaly do
- it_behaves_like 'add_remote'
+ expect(rugged.remotes[remote_name]).not_to be_nil
+ expect(rugged.config["remote.#{remote_name}.mirror"]).to eq('true')
+ expect(rugged.config["remote.#{remote_name}.prune"]).to eq('true')
+ expect(rugged.config["remote.#{remote_name}.fetch"]).to eq(mirror_refmap)
end
end
describe '#remove_remote' do
- shared_examples 'remove_remote' do
- it 'removes the remote' do
- rugged.remotes.create(remote_name, url)
-
- repository.remove_remote(remote_name)
-
- expect(rugged.remotes[remote_name]).to be_nil
- end
- end
-
- context 'using Gitaly' do
- it_behaves_like 'remove_remote'
- end
-
- context 'with Gitaly disabled', :disable_gitaly do
- it_behaves_like 'remove_remote'
- end
- end
- end
+ it 'removes the remote' do
+ rugged.remotes.create(remote_name, url)
- describe '#gitlab_projects' do
- subject { repository.gitlab_projects }
+ repository.remove_remote(remote_name)
- it do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- expect(subject.shard_path).to eq(storage_path)
+ expect(rugged.remotes[remote_name]).to be_nil
end
end
- it { expect(subject.repository_relative_path).to eq(repository.relative_path) }
end
describe '#bundle_to_disk' do
- shared_examples 'bundling to disk' do
- let(:save_path) { File.join(Dir.tmpdir, "repo-#{SecureRandom.hex}.bundle") }
+ let(:save_path) { File.join(Dir.tmpdir, "repo-#{SecureRandom.hex}.bundle") }
- after do
- FileUtils.rm_rf(save_path)
- end
-
- it 'saves a bundle to disk' do
- repository.bundle_to_disk(save_path)
-
- success = system(
- *%W(#{Gitlab.config.git.bin_path} -C #{repository_path} bundle verify #{save_path}),
- [:out, :err] => '/dev/null'
- )
- expect(success).to be true
- end
+ after do
+ FileUtils.rm_rf(save_path)
end
- context 'when Gitaly bundle_to_disk feature is enabled' do
- it_behaves_like 'bundling to disk'
- end
+ it 'saves a bundle to disk' do
+ repository.bundle_to_disk(save_path)
- context 'when Gitaly bundle_to_disk feature is disabled', :disable_gitaly do
- it_behaves_like 'bundling to disk'
+ success = system(
+ *%W(#{Gitlab.config.git.bin_path} -C #{repository_path} bundle verify #{save_path}),
+ [:out, :err] => '/dev/null'
+ )
+ expect(success).to be true
end
end
@@ -2013,138 +1790,41 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
- context 'gitlab_projects commands' do
- let(:gitlab_projects) { repository.gitlab_projects }
- let(:timeout) { Gitlab.config.gitlab_shell.git_timeout }
+ describe '#clean_stale_repository_files' do
+ let(:worktree_path) { File.join(repository_path, 'worktrees', 'delete-me') }
- describe '#push_remote_branches' do
- subject do
- repository.push_remote_branches('downstream-remote', ['master'])
- end
+ it 'cleans up the files' do
+ create_worktree = %W[git -C #{repository_path} worktree add --detach #{worktree_path} master]
+ raise 'preparation failed' unless system(*create_worktree, err: '/dev/null')
- it 'executes the command' do
- expect(gitlab_projects).to receive(:push_branches)
- .with('downstream-remote', timeout, true, ['master'])
- .and_return(true)
+ FileUtils.touch(worktree_path, mtime: Time.now - 8.hours)
+ # git rev-list --all will fail in git 2.16 if HEAD is pointing to a non-existent object,
+ # but the HEAD must be 40 characters long or git will ignore it.
+ File.write(File.join(worktree_path, 'HEAD'), Gitlab::Git::BLANK_SHA)
- is_expected.to be_truthy
- end
+ # git 2.16 fails with "fatal: bad object HEAD"
+ expect(rev_list_all).to be false
- it 'raises an error if the command fails' do
- allow(gitlab_projects).to receive(:output) { 'error' }
- expect(gitlab_projects).to receive(:push_branches)
- .with('downstream-remote', timeout, true, ['master'])
- .and_return(false)
+ repository.clean_stale_repository_files
- expect { subject }.to raise_error(Gitlab::Git::CommandError, 'error')
- end
+ expect(rev_list_all).to be true
+ expect(File.exist?(worktree_path)).to be_falsey
end
- describe '#delete_remote_branches' do
- subject do
- repository.delete_remote_branches('downstream-remote', ['master'])
- end
-
- it 'executes the command' do
- expect(gitlab_projects).to receive(:delete_remote_branches)
- .with('downstream-remote', ['master'])
- .and_return(true)
-
- is_expected.to be_truthy
- end
-
- it 'raises an error if the command fails' do
- allow(gitlab_projects).to receive(:output) { 'error' }
- expect(gitlab_projects).to receive(:delete_remote_branches)
- .with('downstream-remote', ['master'])
- .and_return(false)
-
- expect { subject }.to raise_error(Gitlab::Git::CommandError, 'error')
- end
- end
-
- describe '#delete_remote_branches' do
- subject do
- repository.delete_remote_branches('downstream-remote', ['master'])
- end
-
- it 'executes the command' do
- expect(gitlab_projects).to receive(:delete_remote_branches)
- .with('downstream-remote', ['master'])
- .and_return(true)
-
- is_expected.to be_truthy
- end
-
- it 'raises an error if the command fails' do
- allow(gitlab_projects).to receive(:output) { 'error' }
- expect(gitlab_projects).to receive(:delete_remote_branches)
- .with('downstream-remote', ['master'])
- .and_return(false)
-
- expect { subject }.to raise_error(Gitlab::Git::CommandError, 'error')
- end
- end
-
- describe '#clean_stale_repository_files' do
- let(:worktree_path) { File.join(repository_path, 'worktrees', 'delete-me') }
-
- it 'cleans up the files' do
- create_worktree = %W[git -C #{repository_path} worktree add --detach #{worktree_path} master]
- raise 'preparation failed' unless system(*create_worktree, err: '/dev/null')
-
- FileUtils.touch(worktree_path, mtime: Time.now - 8.hours)
- # git rev-list --all will fail in git 2.16 if HEAD is pointing to a non-existent object,
- # but the HEAD must be 40 characters long or git will ignore it.
- File.write(File.join(worktree_path, 'HEAD'), Gitlab::Git::BLANK_SHA)
-
- # git 2.16 fails with "fatal: bad object HEAD"
- expect(rev_list_all).to be false
-
- repository.clean_stale_repository_files
-
- expect(rev_list_all).to be true
- expect(File.exist?(worktree_path)).to be_falsey
- end
-
- def rev_list_all
- system(*%W[git -C #{repository_path} rev-list --all], out: '/dev/null', err: '/dev/null')
- end
-
- it 'increments a counter upon an error' do
- expect(repository.gitaly_repository_client).to receive(:cleanup).and_raise(Gitlab::Git::CommandError)
-
- counter = double(:counter)
-
- expect(counter).to receive(:increment)
- expect(Gitlab::Metrics).to receive(:counter).with(:failed_repository_cleanup_total,
- 'Number of failed repository cleanup events').and_return(counter)
-
- repository.clean_stale_repository_files
- end
+ def rev_list_all
+ system(*%W[git -C #{repository_path} rev-list --all], out: '/dev/null', err: '/dev/null')
end
- describe '#delete_remote_branches' do
- subject do
- repository.delete_remote_branches('downstream-remote', ['master'])
- end
+ it 'increments a counter upon an error' do
+ expect(repository.gitaly_repository_client).to receive(:cleanup).and_raise(Gitlab::Git::CommandError)
- it 'executes the command' do
- expect(gitlab_projects).to receive(:delete_remote_branches)
- .with('downstream-remote', ['master'])
- .and_return(true)
+ counter = double(:counter)
- is_expected.to be_truthy
- end
-
- it 'raises an error if the command fails' do
- allow(gitlab_projects).to receive(:output) { 'error' }
- expect(gitlab_projects).to receive(:delete_remote_branches)
- .with('downstream-remote', ['master'])
- .and_return(false)
+ expect(counter).to receive(:increment)
+ expect(Gitlab::Metrics).to receive(:counter).with(:failed_repository_cleanup_total,
+ 'Number of failed repository cleanup events').and_return(counter)
- expect { subject }.to raise_error(Gitlab::Git::CommandError, 'error')
- end
+ repository.clean_stale_repository_files
end
end
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index 54f2ea33f90..bcdf12a00a0 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -19,7 +19,14 @@ describe Gitlab::GitalyClient::CommitService do
right_commit_id: commit.id,
collapse_diffs: false,
enforce_limits: true,
- **Gitlab::Git::DiffCollection.collection_limits.to_h
+ # Tests limitation parameters explicitly
+ max_files: 100,
+ max_lines: 5000,
+ max_bytes: 512000,
+ safe_max_files: 100,
+ safe_max_lines: 5000,
+ safe_max_bytes: 512000,
+ max_patch_bytes: 102400
)
expect_any_instance_of(Gitaly::DiffService::Stub).to receive(:commit_diff).with(request, kind_of(Hash))
@@ -37,7 +44,14 @@ describe Gitlab::GitalyClient::CommitService do
right_commit_id: initial_commit.id,
collapse_diffs: false,
enforce_limits: true,
- **Gitlab::Git::DiffCollection.collection_limits.to_h
+ # Tests limitation parameters explicitly
+ max_files: 100,
+ max_lines: 5000,
+ max_bytes: 512000,
+ safe_max_files: 100,
+ safe_max_lines: 5000,
+ safe_max_bytes: 512000,
+ max_patch_bytes: 102400
)
expect_any_instance_of(Gitaly::DiffService::Stub).to receive(:commit_diff).with(request, kind_of(Hash))
diff --git a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
index f03c7e3f04b..9030a49983d 100644
--- a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
@@ -45,6 +45,26 @@ describe Gitlab::GitalyClient::RemoteService do
end
end
+ describe '#find_remote_root_ref' do
+ it 'sends an find_remote_root_ref message and returns the root ref' do
+ expect_any_instance_of(Gitaly::RemoteService::Stub)
+ .to receive(:find_remote_root_ref)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(ref: 'master'))
+
+ expect(client.find_remote_root_ref('origin')).to eq 'master'
+ end
+
+ it 'ensure ref is a valid UTF-8 string' do
+ expect_any_instance_of(Gitaly::RemoteService::Stub)
+ .to receive(:find_remote_root_ref)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(ref: "an_invalid_ref_\xE5"))
+
+ expect(client.find_remote_root_ref('origin')).to eq "an_invalid_ref_Ã¥"
+ end
+ end
+
describe '#update_remote_mirror' do
let(:ref_name) { 'remote_mirror_1' }
let(:only_branches_matching) { ['my-branch', 'master'] }
diff --git a/spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_object_storage_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_object_storage_spec.rb
deleted file mode 100644
index 5059d68e54b..00000000000
--- a/spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_object_storage_spec.rb
+++ /dev/null
@@ -1,105 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::ImportExport::AfterExportStrategies::BaseAfterExportStrategy do
- let!(:service) { described_class.new }
- let!(:project) { create(:project, :with_object_export) }
- let(:shared) { project.import_export_shared }
- let!(:user) { create(:user) }
-
- describe '#execute' do
- before do
- allow(service).to receive(:strategy_execute)
- stub_feature_flags(import_export_object_storage: true)
- end
-
- it 'returns if project exported file is not found' do
- allow(project).to receive(:export_project_object_exists?).and_return(false)
-
- expect(service).not_to receive(:strategy_execute)
-
- service.execute(user, project)
- end
-
- it 'creates a lock file in the export dir' do
- allow(service).to receive(:delete_after_export_lock)
-
- service.execute(user, project)
-
- expect(lock_path_exist?).to be_truthy
- end
-
- context 'when the method succeeds' do
- it 'removes the lock file' do
- service.execute(user, project)
-
- expect(lock_path_exist?).to be_falsey
- end
- end
-
- context 'when the method fails' do
- before do
- allow(service).to receive(:strategy_execute).and_call_original
- end
-
- context 'when validation fails' do
- before do
- allow(service).to receive(:invalid?).and_return(true)
- end
-
- it 'does not create the lock file' do
- expect(service).not_to receive(:create_or_update_after_export_lock)
-
- service.execute(user, project)
- end
-
- it 'does not execute main logic' do
- expect(service).not_to receive(:strategy_execute)
-
- service.execute(user, project)
- end
-
- it 'logs validation errors in shared context' do
- expect(service).to receive(:log_validation_errors)
-
- service.execute(user, project)
- end
- end
-
- context 'when an exception is raised' do
- it 'removes the lock' do
- expect { service.execute(user, project) }.to raise_error(NotImplementedError)
-
- expect(lock_path_exist?).to be_falsey
- end
- end
- end
- end
-
- describe '#log_validation_errors' do
- it 'add the message to the shared context' do
- errors = %w(test_message test_message2)
-
- allow(service).to receive(:invalid?).and_return(true)
- allow(service.errors).to receive(:full_messages).and_return(errors)
-
- expect(shared).to receive(:add_error_message).twice.and_call_original
-
- service.execute(user, project)
-
- expect(shared.errors).to eq errors
- end
- end
-
- describe '#to_json' do
- it 'adds the current strategy class to the serialized attributes' do
- params = { param1: 1 }
- result = params.merge(klass: described_class.to_s).to_json
-
- expect(described_class.new(params).to_json).to eq result
- end
- end
-
- def lock_path_exist?
- File.exist?(described_class.lock_file_path(project))
- end
-end
diff --git a/spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb
index 566b7f46c87..9a442de2900 100644
--- a/spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb
+++ b/spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb
@@ -9,11 +9,10 @@ describe Gitlab::ImportExport::AfterExportStrategies::BaseAfterExportStrategy do
describe '#execute' do
before do
allow(service).to receive(:strategy_execute)
- stub_feature_flags(import_export_object_storage: false)
end
it 'returns if project exported file is not found' do
- allow(project).to receive(:export_project_path).and_return(nil)
+ allow(project).to receive(:export_file_exists?).and_return(false)
expect(service).not_to receive(:strategy_execute)
diff --git a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
index 7f2e0a4ee2c..ec17ad8541f 100644
--- a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
+++ b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
@@ -24,34 +24,13 @@ describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
end
describe '#execute' do
- context 'without object storage' do
- before do
- stub_feature_flags(import_export_object_storage: false)
- end
-
- it 'removes the exported project file after the upload' do
- allow(strategy).to receive(:send_file)
- allow(strategy).to receive(:handle_response_error)
-
- expect(project).to receive(:remove_exported_project_file)
-
- strategy.execute(user, project)
- end
- end
-
- context 'with object storage' do
- before do
- stub_feature_flags(import_export_object_storage: true)
- end
+ it 'removes the exported project file after the upload' do
+ allow(strategy).to receive(:send_file)
+ allow(strategy).to receive(:handle_response_error)
- it 'removes the exported project file after the upload' do
- allow(strategy).to receive(:send_file)
- allow(strategy).to receive(:handle_response_error)
+ expect(project).to receive(:remove_exports)
- expect(project).to receive(:remove_exported_project_file)
-
- strategy.execute(user, project)
- end
+ strategy.execute(user, project)
end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index b4269bd5786..ec2bdbe22e1 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -288,6 +288,7 @@ project:
- fork_network_member
- fork_network
- custom_attributes
+- prometheus_metrics
- lfs_file_locks
- project_badges
- source_of_merge_requests
@@ -303,6 +304,8 @@ award_emoji:
- user
priorities:
- label
+prometheus_metrics:
+- project
timelogs:
- issue
- merge_request
@@ -321,3 +324,9 @@ metrics:
- latest_closed_by
- merged_by
- pipeline
+resource_label_events:
+- user
+- issue
+- merge_request
+- epic
+- label
diff --git a/spec/lib/gitlab/import_export/avatar_restorer_spec.rb b/spec/lib/gitlab/import_export/avatar_restorer_spec.rb
index 4897d604bc1..e44ff6bbcbd 100644
--- a/spec/lib/gitlab/import_export/avatar_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/avatar_restorer_spec.rb
@@ -6,22 +6,35 @@ describe Gitlab::ImportExport::AvatarRestorer do
let(:shared) { project.import_export_shared }
let(:project) { create(:project) }
- before do
- allow_any_instance_of(described_class).to receive(:avatar_export_file)
- .and_return(uploaded_image_temp_path)
- end
-
after do
project.remove_avatar!
end
- it 'restores a project avatar' do
- expect(described_class.new(project: project, shared: shared).restore).to be true
+ context 'with avatar' do
+ before do
+ allow_any_instance_of(described_class).to receive(:avatar_export_file)
+ .and_return(uploaded_image_temp_path)
+ end
+
+ it 'restores a project avatar' do
+ expect(described_class.new(project: project, shared: shared).restore).to be true
+ end
+
+ it 'saves the avatar into the project' do
+ described_class.new(project: project, shared: shared).restore
+
+ expect(project.reload.avatar.file.exists?).to be true
+ end
end
- it 'saves the avatar into the project' do
- described_class.new(project: project, shared: shared).restore
+ it 'does not break if there is just a directory' do
+ Dir.mktmpdir do |tmpdir|
+ FileUtils.mkdir_p("#{tmpdir}/a/b")
+
+ allow_any_instance_of(described_class).to receive(:avatar_export_path)
+ .and_return("#{tmpdir}/a")
- expect(project.reload.avatar.file.exists?).to be true
+ expect(described_class.new(project: project, shared: shared).restore).to be true
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/avatar_saver_spec.rb b/spec/lib/gitlab/import_export/avatar_saver_spec.rb
index 90e6d653d34..2bd1b9924c6 100644
--- a/spec/lib/gitlab/import_export/avatar_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/avatar_saver_spec.rb
@@ -8,8 +8,7 @@ describe Gitlab::ImportExport::AvatarSaver do
before do
FileUtils.mkdir_p("#{shared.export_path}/avatar/")
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
- stub_feature_flags(import_export_object_storage: false)
+ allow_any_instance_of(Gitlab::ImportExport::Shared).to receive(:export_path).and_return(export_path)
end
after do
@@ -19,7 +18,7 @@ describe Gitlab::ImportExport::AvatarSaver do
it 'saves a project avatar' do
described_class.new(project: project_with_avatar, shared: shared).save
- expect(File).to exist("#{shared.export_path}/avatar/dk.png")
+ expect(File).to exist(Dir["#{shared.export_path}/avatar/**/dk.png"].first)
end
it 'is fine not to have an avatar' do
diff --git a/spec/lib/gitlab/import_export/file_importer_object_storage_spec.rb b/spec/lib/gitlab/import_export/file_importer_object_storage_spec.rb
deleted file mode 100644
index 287745eb40e..00000000000
--- a/spec/lib/gitlab/import_export/file_importer_object_storage_spec.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::ImportExport::FileImporter do
- let(:shared) { Gitlab::ImportExport::Shared.new(nil) }
- let(:storage_path) { "#{Dir.tmpdir}/file_importer_spec" }
- let(:valid_file) { "#{shared.export_path}/valid.json" }
- let(:symlink_file) { "#{shared.export_path}/invalid.json" }
- let(:hidden_symlink_file) { "#{shared.export_path}/.hidden" }
- let(:subfolder_symlink_file) { "#{shared.export_path}/subfolder/invalid.json" }
- let(:evil_symlink_file) { "#{shared.export_path}/.\nevil" }
-
- before do
- stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0)
- stub_feature_flags(import_export_object_storage: true)
- stub_uploads_object_storage(FileUploader)
-
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(storage_path)
- allow_any_instance_of(Gitlab::ImportExport::CommandLineUtil).to receive(:untar_zxf).and_return(true)
- allow_any_instance_of(Gitlab::ImportExport::Shared).to receive(:relative_archive_path).and_return('test')
- allow(SecureRandom).to receive(:hex).and_return('abcd')
- setup_files
- end
-
- after do
- FileUtils.rm_rf(storage_path)
- end
-
- context 'normal run' do
- before do
- described_class.import(project: build(:project), archive_file: '', shared: shared)
- end
-
- it 'removes symlinks in root folder' do
- expect(File.exist?(symlink_file)).to be false
- end
-
- it 'removes hidden symlinks in root folder' do
- expect(File.exist?(hidden_symlink_file)).to be false
- end
-
- it 'removes evil symlinks in root folder' do
- expect(File.exist?(evil_symlink_file)).to be false
- end
-
- it 'removes symlinks in subfolders' do
- expect(File.exist?(subfolder_symlink_file)).to be false
- end
-
- it 'does not remove a valid file' do
- expect(File.exist?(valid_file)).to be true
- end
-
- it 'creates the file in the right subfolder' do
- expect(shared.export_path).to include('test/abcd')
- end
- end
-
- context 'error' do
- before do
- allow_any_instance_of(described_class).to receive(:wait_for_archived_file).and_raise(StandardError)
- described_class.import(project: build(:project), archive_file: '', shared: shared)
- end
-
- it 'removes symlinks in root folder' do
- expect(File.exist?(symlink_file)).to be false
- end
-
- it 'removes hidden symlinks in root folder' do
- expect(File.exist?(hidden_symlink_file)).to be false
- end
-
- it 'removes symlinks in subfolders' do
- expect(File.exist?(subfolder_symlink_file)).to be false
- end
-
- it 'does not remove a valid file' do
- expect(File.exist?(valid_file)).to be true
- end
- end
-
- def setup_files
- FileUtils.mkdir_p("#{shared.export_path}/subfolder/")
- FileUtils.touch(valid_file)
- FileUtils.ln_s(valid_file, symlink_file)
- FileUtils.ln_s(valid_file, subfolder_symlink_file)
- FileUtils.ln_s(valid_file, hidden_symlink_file)
- FileUtils.ln_s(valid_file, evil_symlink_file)
- end
-end
diff --git a/spec/lib/gitlab/import_export/file_importer_spec.rb b/spec/lib/gitlab/import_export/file_importer_spec.rb
index 78fccdf1dfc..bf34cefe18f 100644
--- a/spec/lib/gitlab/import_export/file_importer_spec.rb
+++ b/spec/lib/gitlab/import_export/file_importer_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::ImportExport::FileImporter do
let(:shared) { Gitlab::ImportExport::Shared.new(nil) }
- let(:export_path) { "#{Dir.tmpdir}/file_importer_spec" }
+ let(:storage_path) { "#{Dir.tmpdir}/file_importer_spec" }
let(:valid_file) { "#{shared.export_path}/valid.json" }
let(:symlink_file) { "#{shared.export_path}/invalid.json" }
let(:hidden_symlink_file) { "#{shared.export_path}/.hidden" }
@@ -11,7 +11,9 @@ describe Gitlab::ImportExport::FileImporter do
before do
stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0)
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ stub_uploads_object_storage(FileUploader)
+
+ allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(storage_path)
allow_any_instance_of(Gitlab::ImportExport::CommandLineUtil).to receive(:untar_zxf).and_return(true)
allow_any_instance_of(Gitlab::ImportExport::Shared).to receive(:relative_archive_path).and_return('test')
allow(SecureRandom).to receive(:hex).and_return('abcd')
@@ -19,12 +21,12 @@ describe Gitlab::ImportExport::FileImporter do
end
after do
- FileUtils.rm_rf(export_path)
+ FileUtils.rm_rf(storage_path)
end
context 'normal run' do
before do
- described_class.import(project: nil, archive_file: '', shared: shared)
+ described_class.import(project: build(:project), archive_file: '', shared: shared)
end
it 'removes symlinks in root folder' do
@@ -55,7 +57,7 @@ describe Gitlab::ImportExport::FileImporter do
context 'error' do
before do
allow_any_instance_of(described_class).to receive(:wait_for_archived_file).and_raise(StandardError)
- described_class.import(project: nil, archive_file: '', shared: shared)
+ described_class.import(project: build(:project), archive_file: '', shared: shared)
end
it 'removes symlinks in root folder' do
diff --git a/spec/lib/gitlab/import_export/importer_object_storage_spec.rb b/spec/lib/gitlab/import_export/importer_object_storage_spec.rb
deleted file mode 100644
index 24a994b3611..00000000000
--- a/spec/lib/gitlab/import_export/importer_object_storage_spec.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::ImportExport::Importer do
- let(:user) { create(:user) }
- let(:test_path) { "#{Dir.tmpdir}/importer_spec" }
- let(:shared) { project.import_export_shared }
- let(:project) { create(:project) }
- let(:import_file) { fixture_file_upload('spec/features/projects/import_export/test_project_export.tar.gz') }
-
- subject(:importer) { described_class.new(project) }
-
- before do
- allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(test_path)
- allow_any_instance_of(Gitlab::ImportExport::FileImporter).to receive(:remove_import_file)
- stub_feature_flags(import_export_object_storage: true)
- stub_uploads_object_storage(FileUploader)
-
- FileUtils.mkdir_p(shared.export_path)
- ImportExportUpload.create(project: project, import_file: import_file)
- end
-
- after do
- FileUtils.rm_rf(test_path)
- end
-
- describe '#execute' do
- it 'succeeds' do
- importer.execute
-
- expect(shared.errors).to be_empty
- end
-
- it 'extracts the archive' do
- expect(Gitlab::ImportExport::FileImporter).to receive(:import).and_call_original
-
- importer.execute
- end
-
- it 'checks the version' do
- expect(Gitlab::ImportExport::VersionChecker).to receive(:check!).and_call_original
-
- importer.execute
- end
-
- context 'all restores are executed' do
- [
- Gitlab::ImportExport::AvatarRestorer,
- Gitlab::ImportExport::RepoRestorer,
- Gitlab::ImportExport::WikiRestorer,
- Gitlab::ImportExport::UploadsRestorer,
- Gitlab::ImportExport::LfsRestorer,
- Gitlab::ImportExport::StatisticsRestorer
- ].each do |restorer|
- it "calls the #{restorer}" do
- fake_restorer = double(restorer.to_s)
-
- expect(fake_restorer).to receive(:restore).and_return(true).at_least(1)
- expect(restorer).to receive(:new).and_return(fake_restorer).at_least(1)
-
- importer.execute
- end
- end
-
- it 'restores the ProjectTree' do
- expect(Gitlab::ImportExport::ProjectTreeRestorer).to receive(:new).and_call_original
-
- importer.execute
- end
-
- it 'removes the import file' do
- expect(importer).to receive(:remove_import_file).and_call_original
-
- importer.execute
-
- expect(project.import_export_upload.import_file&.file).to be_nil
- end
- end
-
- context 'when project successfully restored' do
- let!(:existing_project) { create(:project, namespace: user.namespace) }
- let(:project) { create(:project, namespace: user.namespace, name: 'whatever', path: 'whatever') }
-
- before do
- restorers = double(:restorers, all?: true)
-
- allow(subject).to receive(:import_file).and_return(true)
- allow(subject).to receive(:check_version!).and_return(true)
- allow(subject).to receive(:restorers).and_return(restorers)
- allow(project).to receive(:import_data).and_return(double(data: { 'original_path' => existing_project.path }))
- end
-
- context 'when import_data' do
- context 'has original_path' do
- it 'overwrites existing project' do
- expect_any_instance_of(::Projects::OverwriteProjectService).to receive(:execute).with(existing_project)
-
- subject.execute
- end
- end
-
- context 'has not original_path' do
- before do
- allow(project).to receive(:import_data).and_return(double(data: {}))
- end
-
- it 'does not call the overwrite service' do
- expect_any_instance_of(::Projects::OverwriteProjectService).not_to receive(:execute).with(existing_project)
-
- subject.execute
- end
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/import_export/importer_spec.rb b/spec/lib/gitlab/import_export/importer_spec.rb
index 8053c48ad6c..11f98d782b1 100644
--- a/spec/lib/gitlab/import_export/importer_spec.rb
+++ b/spec/lib/gitlab/import_export/importer_spec.rb
@@ -4,16 +4,18 @@ describe Gitlab::ImportExport::Importer do
let(:user) { create(:user) }
let(:test_path) { "#{Dir.tmpdir}/importer_spec" }
let(:shared) { project.import_export_shared }
- let(:project) { create(:project, import_source: File.join(test_path, 'test_project_export.tar.gz')) }
+ let(:project) { create(:project) }
+ let(:import_file) { fixture_file_upload('spec/features/projects/import_export/test_project_export.tar.gz') }
subject(:importer) { described_class.new(project) }
before do
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(test_path)
allow_any_instance_of(Gitlab::ImportExport::FileImporter).to receive(:remove_import_file)
+ stub_uploads_object_storage(FileUploader)
FileUtils.mkdir_p(shared.export_path)
- FileUtils.cp(Rails.root.join('spec/features/projects/import_export/test_project_export.tar.gz'), test_path)
+ ImportExportUpload.create(project: project, import_file: import_file)
end
after do
@@ -64,6 +66,14 @@ describe Gitlab::ImportExport::Importer do
importer.execute
end
+ it 'removes the import file' do
+ expect(importer).to receive(:remove_import_file).and_call_original
+
+ importer.execute
+
+ expect(project.import_export_upload.import_file&.file).to be_nil
+ end
+
it 'sets the correct visibility_level when visibility level is a string' do
project.create_or_update_import_data(
data: { override_params: { visibility_level: Gitlab::VisibilityLevel::PRIVATE.to_s } }
@@ -85,7 +95,6 @@ describe Gitlab::ImportExport::Importer do
allow(subject).to receive(:import_file).and_return(true)
allow(subject).to receive(:check_version!).and_return(true)
allow(subject).to receive(:restorers).and_return(restorers)
- allow(restorers).to receive(:all?).and_return(true)
allow(project).to receive(:import_data).and_return(double(data: { 'original_path' => existing_project.path }))
end
diff --git a/spec/lib/gitlab/import_export/model_configuration_spec.rb b/spec/lib/gitlab/import_export/model_configuration_spec.rb
index 5cb8f2589c8..2e28f978c3a 100644
--- a/spec/lib/gitlab/import_export/model_configuration_spec.rb
+++ b/spec/lib/gitlab/import_export/model_configuration_spec.rb
@@ -16,14 +16,30 @@ describe 'Import/Export model configuration' do
# - User, Author... Models we do not care about for checking models
names.flatten.uniq - %w(milestones labels user author) + ['project']
end
+ let(:ce_models_yml) { 'spec/lib/gitlab/import_export/all_models.yml' }
+ let(:ce_models_hash) { YAML.load_file(ce_models_yml) }
+
+ let(:ee_models_yml) { 'ee/spec/lib/gitlab/import_export/all_models.yml' }
+ let(:ee_models_hash) { File.exist?(ee_models_yml) ? YAML.load_file(ee_models_yml) : {} }
- let(:all_models_yml) { 'spec/lib/gitlab/import_export/all_models.yml' }
- let(:all_models) { YAML.load_file(all_models_yml) }
let(:current_models) { setup_models }
+ let(:all_models_hash) do
+ all_models_hash = ce_models_hash.dup
+
+ all_models_hash.each do |model, associations|
+ associations.concat(ee_models_hash[model] || [])
+ end
+
+ ee_models_hash.each do |model, associations|
+ all_models_hash[model] ||= associations
+ end
+
+ all_models_hash
+ end
it 'has no new models' do
model_names.each do |model_name|
- new_models = Array(current_models[model_name]) - Array(all_models[model_name])
+ new_models = Array(current_models[model_name]) - Array(all_models_hash[model_name])
expect(new_models).to be_empty, failure_message(model_name.classify, new_models)
end
end
@@ -31,27 +47,21 @@ describe 'Import/Export model configuration' do
# List of current models between models, in the format of
# {model: [model_2, model3], ...}
def setup_models
- all_models_hash = {}
-
- model_names.each do |model_name|
- model_class = relation_class_for_name(model_name)
-
- all_models_hash[model_name] = associations_for(model_class) - ['project']
+ model_names.each_with_object({}) do |model_name, hash|
+ hash[model_name] = associations_for(relation_class_for_name(model_name)) - ['project']
end
-
- all_models_hash
end
def failure_message(parent_model_name, new_models)
- <<-MSG
+ <<~MSG
New model(s) <#{new_models.join(',')}> have been added, related to #{parent_model_name}, which is exported by
the Import/Export feature.
- If you think this model should be included in the export, please add it to IMPORT_EXPORT_CONFIG.
- Definitely add it to MODELS_JSON to signal that you've handled this error and to prevent it from showing up in the future.
+ If you think this model should be included in the export, please add it to `#{Gitlab::ImportExport.config_file}`.
- MODELS_JSON: #{File.expand_path(all_models_yml)}
- IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file}
+ Definitely add it to `#{File.expand_path(ce_models_yml)}`
+ #{"or `#{File.expand_path(ee_models_yml)}` if the model/associations are EE-specific\n" if ee_models_hash.any?}
+ to signal that you've handled this error and to prevent it from showing up in the future.
MSG
end
end
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 1b7fa11cb3c..eefd00e7383 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -331,6 +331,28 @@
},
"events": []
}
+ ],
+ "resource_label_events": [
+ {
+ "id":244,
+ "action":"remove",
+ "issue_id":40,
+ "merge_request_id":null,
+ "label_id":2,
+ "user_id":1,
+ "created_at":"2018-08-28T08:24:00.494Z",
+ "label": {
+ "id": 2,
+ "title": "test2",
+ "color": "#428bca",
+ "project_id": 8,
+ "created_at": "2016-07-22T08:55:44.161Z",
+ "updated_at": "2016-07-22T08:55:44.161Z",
+ "template": false,
+ "description": "",
+ "type": "ProjectLabel"
+ }
+ }
]
},
{
@@ -2515,6 +2537,17 @@
"events": []
}
],
+ "resource_label_events": [
+ {
+ "id":243,
+ "action":"add",
+ "issue_id":null,
+ "merge_request_id":27,
+ "label_id":null,
+ "user_id":1,
+ "created_at":"2018-08-28T08:24:00.494Z"
+ }
+ ],
"merge_request_diff": {
"id": 27,
"state": "collected",
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index a88ac0a091e..3ff6be595a8 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -89,6 +89,14 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
expect(ProtectedTag.first.create_access_levels).not_to be_empty
end
+ it 'restores issue resource label events' do
+ expect(Issue.find_by(title: 'Voluptatem').resource_label_events).not_to be_empty
+ end
+
+ it 'restores merge requests resource label events' do
+ expect(MergeRequest.find_by(title: 'MR1').resource_label_events).not_to be_empty
+ end
+
context 'event at forth level of the tree' do
let(:event) { Event.where(action: 6).first }
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index fec8a2af9ab..5dc372263ad 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -169,6 +169,14 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
expect(priorities.flatten).not_to be_empty
end
+ it 'has issue resource label events' do
+ expect(saved_project_json['issues'].first['resource_label_events']).not_to be_empty
+ end
+
+ it 'has merge request resource label events' do
+ expect(saved_project_json['merge_requests'].first['resource_label_events']).not_to be_empty
+ end
+
it 'saves the correct service type' do
expect(saved_project_json['services'].first['type']).to eq('CustomIssueTrackerService')
end
@@ -291,6 +299,9 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
project: project,
commit_id: ci_build.pipeline.sha)
+ create(:resource_label_event, label: project_label, issue: issue)
+ create(:resource_label_event, label: group_label, merge_request: merge_request)
+
create(:event, :created, target: milestone, project: project, author: user)
create(:service, project: project, type: 'CustomIssueTrackerService', category: 'issue_tracker', properties: { one: 'value' })
diff --git a/spec/lib/gitlab/import_export/repo_restorer_spec.rb b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
index 7ffa84f906d..8a699eb1461 100644
--- a/spec/lib/gitlab/import_export/repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Gitlab::ImportExport::RepoRestorer do
+ include GitHelpers
+
describe 'bundle a project Git repo' do
let(:user) { create(:user) }
let!(:project_with_repo) { create(:project, :repository, name: 'test-repo-restorer', path: 'test-repo-restorer') }
@@ -36,9 +38,7 @@ describe Gitlab::ImportExport::RepoRestorer do
it 'has the webhooks' do
restorer.restore
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- expect(Gitlab::Git::Hook.new('post-receive', project.repository.raw_repository)).to exist
- end
+ expect(project_hook_exists?(project)).to be true
end
end
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 579f175c4a8..e9f1be172b0 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -555,6 +555,19 @@ ProjectCustomAttribute:
- project_id
- key
- value
+PrometheusMetric:
+- id
+- created_at
+- updated_at
+- project_id
+- y_label
+- unit
+- legend
+- title
+- query
+- group
+- common
+- identifier
Badge:
- id
- link_url
@@ -566,3 +579,11 @@ Badge:
- type
ProjectCiCdSetting:
- group_runners_enabled
+ResourceLabelEvent:
+- id
+- action
+- issue_id
+- merge_request_id
+- label_id
+- user_id
+- created_at
diff --git a/spec/lib/gitlab/import_export/saver_spec.rb b/spec/lib/gitlab/import_export/saver_spec.rb
index 02f1a4b81aa..d185ff2dfcc 100644
--- a/spec/lib/gitlab/import_export/saver_spec.rb
+++ b/spec/lib/gitlab/import_export/saver_spec.rb
@@ -18,26 +18,12 @@ describe Gitlab::ImportExport::Saver do
FileUtils.rm_rf(export_path)
end
- context 'local archive' do
- it 'saves the repo to disk' do
- stub_feature_flags(import_export_object_storage: false)
+ it 'saves the repo using object storage' do
+ stub_uploads_object_storage(ImportExportUploader)
- subject.save
+ subject.save
- expect(shared.errors).to be_empty
- expect(Dir.empty?(shared.archive_path)).to be false
- end
- end
-
- context 'object storage' do
- it 'saves the repo using object storage' do
- stub_feature_flags(import_export_object_storage: true)
- stub_uploads_object_storage(ImportExportUploader)
-
- subject.save
-
- expect(ImportExportUpload.find_by(project: project).export_file.url)
- .to match(%r[\/uploads\/-\/system\/import_export_upload\/export_file.*])
- end
+ expect(ImportExportUpload.find_by(project: project).export_file.url)
+ .to match(%r[\/uploads\/-\/system\/import_export_upload\/export_file.*])
end
end
diff --git a/spec/lib/gitlab/import_export/uploads_manager_spec.rb b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
index f799de18cd0..792117e1df1 100644
--- a/spec/lib/gitlab/import_export/uploads_manager_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
@@ -4,6 +4,7 @@ describe Gitlab::ImportExport::UploadsManager do
let(:shared) { project.import_export_shared }
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:project) { create(:project) }
+ let(:upload) { create(:upload, :issuable_upload, :object_storage, model: project) }
let(:exported_file_path) { "#{shared.export_path}/uploads/#{upload.secret}/#{File.basename(upload.path)}" }
subject(:manager) { described_class.new(project: project, shared: shared) }
@@ -69,44 +70,20 @@ describe Gitlab::ImportExport::UploadsManager do
end
end
end
+ end
- context 'using object storage' do
- let!(:upload) { create(:upload, :issuable_upload, :object_storage, model: project) }
-
- before do
- stub_feature_flags(import_export_object_storage: true)
- stub_uploads_object_storage(FileUploader)
- end
-
- it 'saves the file' do
- fake_uri = double
-
- expect(fake_uri).to receive(:open).and_return(StringIO.new('File content'))
- expect(URI).to receive(:parse).and_return(fake_uri)
-
- manager.save
+ describe '#restore' do
+ before do
+ stub_uploads_object_storage(FileUploader)
- expect(File.read(exported_file_path)).to eq('File content')
- end
+ FileUtils.mkdir_p(File.join(shared.export_path, 'uploads/72a497a02fe3ee09edae2ed06d390038'))
+ FileUtils.touch(File.join(shared.export_path, 'uploads/72a497a02fe3ee09edae2ed06d390038', "dummy.txt"))
end
- describe '#restore' do
- context 'using object storage' do
- before do
- stub_feature_flags(import_export_object_storage: true)
- stub_uploads_object_storage(FileUploader)
-
- FileUtils.mkdir_p(File.join(shared.export_path, 'uploads/72a497a02fe3ee09edae2ed06d390038'))
- FileUtils.touch(File.join(shared.export_path, 'uploads/72a497a02fe3ee09edae2ed06d390038', "dummy.txt"))
- end
+ it 'restores the file' do
+ manager.restore
- it 'restores the file' do
- manager.restore
-
- expect(project.uploads.size).to eq(1)
- expect(project.uploads.first.build_uploader.filename).to eq('dummy.txt')
- end
- end
+ expect(project.uploads.map { |u| u.build_uploader.filename }).to include('dummy.txt')
end
end
end
diff --git a/spec/lib/gitlab/import_export/uploads_restorer_spec.rb b/spec/lib/gitlab/import_export/uploads_restorer_spec.rb
index acef97459b8..6072f18b8c7 100644
--- a/spec/lib/gitlab/import_export/uploads_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_restorer_spec.rb
@@ -8,7 +8,7 @@ describe Gitlab::ImportExport::UploadsRestorer do
before do
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
FileUtils.mkdir_p(File.join(shared.export_path, 'uploads/random'))
- FileUtils.touch(File.join(shared.export_path, 'uploads/random', "dummy.txt"))
+ FileUtils.touch(File.join(shared.export_path, 'uploads/random', 'dummy.txt'))
end
after do
@@ -27,9 +27,7 @@ describe Gitlab::ImportExport::UploadsRestorer do
it 'copies the uploads to the project path' do
subject.restore
- uploads = Dir.glob(File.join(subject.uploads_path, '**/*')).map { |file| File.basename(file) }
-
- expect(uploads).to include('dummy.txt')
+ expect(project.uploads.map { |u| u.build_uploader.filename }).to include('dummy.txt')
end
end
@@ -45,9 +43,7 @@ describe Gitlab::ImportExport::UploadsRestorer do
it 'copies the uploads to the project path' do
subject.restore
- uploads = Dir.glob(File.join(subject.uploads_path, '**/*')).map { |file| File.basename(file) }
-
- expect(uploads).to include('dummy.txt')
+ expect(project.uploads.map { |u| u.build_uploader.filename }).to include('dummy.txt')
end
end
end
diff --git a/spec/lib/gitlab/import_export/uploads_saver_spec.rb b/spec/lib/gitlab/import_export/uploads_saver_spec.rb
index c716edd9397..24993460e51 100644
--- a/spec/lib/gitlab/import_export/uploads_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_saver_spec.rb
@@ -7,7 +7,6 @@ describe Gitlab::ImportExport::UploadsSaver do
let(:shared) { project.import_export_shared }
before do
- stub_feature_flags(import_export_object_storage: false)
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
end
diff --git a/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb b/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb
index 5589db92b1d..1a108003bc2 100644
--- a/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb
+++ b/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::Prometheus::AdditionalMetricsParser do
let(:parser_error_class) { Gitlab::Prometheus::ParsingError }
describe '#load_groups_from_yaml' do
- subject { described_class.load_groups_from_yaml }
+ subject { described_class.load_groups_from_yaml('dummy.yaml') }
describe 'parsing sample yaml' do
let(:sample_yaml) do
diff --git a/spec/lib/gitlab/prometheus/metric_group_spec.rb b/spec/lib/gitlab/prometheus/metric_group_spec.rb
new file mode 100644
index 00000000000..e7d16e73663
--- /dev/null
+++ b/spec/lib/gitlab/prometheus/metric_group_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Gitlab::Prometheus::MetricGroup do
+ describe '.common_metrics' do
+ let!(:project_metric) { create(:prometheus_metric) }
+ let!(:common_metric_group_a) { create(:prometheus_metric, :common, group: :aws_elb) }
+ let!(:common_metric_group_b_q1) { create(:prometheus_metric, :common, group: :kubernetes) }
+ let!(:common_metric_group_b_q2) { create(:prometheus_metric, :common, group: :kubernetes) }
+
+ subject { described_class.common_metrics }
+
+ it 'returns exactly two groups' do
+ expect(subject.map(&:name)).to contain_exactly(
+ 'Response metrics (AWS ELB)', 'System metrics (Kubernetes)')
+ end
+
+ it 'returns exactly three metric queries' do
+ expect(subject.map(&:metrics).flatten.map(&:id)).to contain_exactly(
+ common_metric_group_a.id, common_metric_group_b_q1.id,
+ common_metric_group_b_q2.id)
+ end
+ end
+
+ describe '.for_project' do
+ let!(:other_project) { create(:project) }
+ let!(:project_metric) { create(:prometheus_metric) }
+ let!(:common_metric) { create(:prometheus_metric, :common, group: :aws_elb) }
+
+ subject do
+ described_class.for_project(other_project)
+ .map(&:metrics).flatten
+ .map(&:id)
+ end
+
+ it 'returns exactly one common metric' do
+ is_expected.to contain_exactly(common_metric.id)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index f8bf896950e..b1b7c427313 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -7,15 +7,10 @@ describe Gitlab::Shell do
let(:repository) { project.repository }
let(:gitlab_shell) { described_class.new }
let(:popen_vars) { { 'GIT_TERMINAL_PROMPT' => ENV['GIT_TERMINAL_PROMPT'] } }
- let(:gitlab_projects) { double('gitlab_projects') }
let(:timeout) { Gitlab.config.gitlab_shell.git_timeout }
before do
allow(Project).to receive(:find).and_return(project)
-
- allow(gitlab_shell).to receive(:gitlab_projects)
- .with(project.repository_storage, project.disk_path + '.git')
- .and_return(gitlab_projects)
end
it { is_expected.to respond_to :add_key }
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 23869f3d2da..b3f55a2e1bd 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -336,6 +336,22 @@ describe Gitlab::Workhorse do
it { expect { subject }.to raise_exception('Unsupported action: download') }
end
end
+
+ context 'when receive_max_input_size has been updated' do
+ it 'returns custom git config' do
+ allow(Gitlab::CurrentSettings).to receive(:receive_max_input_size) { 1 }
+
+ expect(subject[:GitConfigOptions]).to be_present
+ end
+ end
+
+ context 'when receive_max_input_size is empty' do
+ it 'returns an empty git config' do
+ allow(Gitlab::CurrentSettings).to receive(:receive_max_input_size) { nil }
+
+ expect(subject[:GitConfigOptions]).to be_empty
+ end
+ end
end
describe '.set_key_and_notify' do