2018-10-17 07:33:54 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
2020-06-24 11:08:50 -04:00
|
|
|
RSpec.describe Projects::AfterRenameService do
|
2018-10-17 07:33:54 -04:00
|
|
|
let(:rugged_config) { rugged_repo(project.repository).config }
|
2019-01-16 20:53:50 -05:00
|
|
|
let(:legacy_storage) { Storage::LegacyProject.new(project) }
|
2020-02-04 07:09:00 -05:00
|
|
|
let(:hashed_storage) { Storage::Hashed.new(project) }
|
2019-01-16 20:53:50 -05:00
|
|
|
let!(:path_before_rename) { project.path }
|
2019-01-21 22:33:32 -05:00
|
|
|
let!(:full_path_before_rename) { project.full_path }
|
2019-01-16 20:53:50 -05:00
|
|
|
let!(:path_after_rename) { "#{project.path}-renamed" }
|
2019-01-21 22:33:32 -05:00
|
|
|
let!(:full_path_after_rename) { "#{project.full_path}-renamed" }
|
2018-10-17 07:33:54 -04:00
|
|
|
|
|
|
|
describe '#execute' do
|
|
|
|
context 'using legacy storage' do
|
2019-01-21 22:33:32 -05:00
|
|
|
let(:project) { create(:project, :repository, :wiki_repo, :legacy_storage) }
|
2018-10-17 07:33:54 -04:00
|
|
|
let(:project_storage) { project.send(:storage) }
|
2019-01-16 20:53:50 -05:00
|
|
|
let(:gitlab_shell) { Gitlab::Shell.new }
|
2018-10-17 07:33:54 -04:00
|
|
|
|
|
|
|
before do
|
|
|
|
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
|
|
|
|
# call. This makes testing a bit easier.
|
|
|
|
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
|
|
|
|
|
2019-06-12 23:18:05 -04:00
|
|
|
stub_application_setting(hashed_storage_enabled: false)
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'renames a repository' do
|
|
|
|
stub_container_registry_config(enabled: false)
|
|
|
|
|
|
|
|
expect_any_instance_of(SystemHooksService)
|
|
|
|
.to receive(:execute_hooks_for)
|
|
|
|
.with(project, :rename)
|
|
|
|
|
|
|
|
expect_any_instance_of(Gitlab::UploadsTransfer)
|
|
|
|
.to receive(:rename_project)
|
2019-01-16 20:53:50 -05:00
|
|
|
.with(path_before_rename, path_after_rename, project.namespace.full_path)
|
2018-10-17 07:33:54 -04:00
|
|
|
|
2019-01-21 22:33:32 -05:00
|
|
|
expect_repository_exist("#{full_path_before_rename}.git")
|
|
|
|
expect_repository_exist("#{full_path_before_rename}.wiki.git")
|
2018-10-17 07:33:54 -04:00
|
|
|
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2019-01-21 22:33:32 -05:00
|
|
|
|
|
|
|
expect_repository_exist("#{full_path_after_rename}.git")
|
|
|
|
expect_repository_exist("#{full_path_after_rename}.wiki.git")
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'container registry with images' do
|
|
|
|
let(:container_repository) { create(:container_repository) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
stub_container_registry_config(enabled: true)
|
|
|
|
stub_container_registry_tags(repository: :any, tags: ['tag'])
|
|
|
|
project.container_repositories << container_repository
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'raises a RenameFailedError' do
|
2019-01-16 20:53:50 -05:00
|
|
|
expect { service_execute }.to raise_error(described_class::RenameFailedError)
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'gitlab pages' do
|
|
|
|
before do
|
2020-08-26 08:10:53 -04:00
|
|
|
allow(project_storage).to receive(:rename_repo) { true }
|
|
|
|
end
|
|
|
|
|
2020-08-27 11:10:21 -04:00
|
|
|
context 'when the project has pages deployed' do
|
|
|
|
it 'schedules a move of the pages directory' do
|
|
|
|
allow(project).to receive(:pages_deployed?).and_return(true)
|
2018-10-17 07:33:54 -04:00
|
|
|
|
2020-08-27 11:10:21 -04:00
|
|
|
expect(PagesTransferWorker).to receive(:perform_async).with('rename_project', anything)
|
|
|
|
|
|
|
|
service_execute
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the project does not have pages deployed' do
|
|
|
|
it 'does nothing with the pages directory' do
|
|
|
|
allow(project).to receive(:pages_deployed?).and_return(false)
|
|
|
|
|
|
|
|
expect(PagesTransferWorker).not_to receive(:perform_async)
|
|
|
|
expect(Gitlab::PagesTransfer).not_to receive(:new)
|
|
|
|
|
|
|
|
service_execute
|
|
|
|
end
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'attachments' do
|
|
|
|
before do
|
|
|
|
expect(project_storage).to receive(:rename_repo) { true }
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'moves uploads folder to new location' do
|
|
|
|
expect_any_instance_of(Gitlab::UploadsTransfer).to receive(:rename_project)
|
|
|
|
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'updates project full path in .git/config' do
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2018-10-17 07:33:54 -04:00
|
|
|
|
|
|
|
expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
|
|
|
|
end
|
2018-12-18 14:00:27 -05:00
|
|
|
|
|
|
|
it 'updates storage location' do
|
|
|
|
allow(project_storage).to receive(:rename_repo).and_return(true)
|
|
|
|
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2018-12-18 14:00:27 -05:00
|
|
|
|
|
|
|
expect(project.project_repository).to have_attributes(
|
|
|
|
disk_path: project.disk_path,
|
|
|
|
shard_name: project.repository_storage
|
|
|
|
)
|
|
|
|
end
|
2019-01-16 20:53:50 -05:00
|
|
|
|
|
|
|
context 'with hashed storage upgrade when renaming enabled' do
|
2019-01-14 22:30:55 -05:00
|
|
|
it 'calls HashedStorage::MigrationService with correct options' do
|
2019-01-16 20:53:50 -05:00
|
|
|
stub_application_setting(hashed_storage_enabled: true)
|
|
|
|
|
2019-01-14 22:30:55 -05:00
|
|
|
expect_next_instance_of(::Projects::HashedStorage::MigrationService) do |service|
|
2019-01-16 20:53:50 -05:00
|
|
|
expect(service).to receive(:execute).and_return(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
service_execute
|
|
|
|
end
|
|
|
|
end
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'using hashed storage' do
|
2019-01-21 22:33:32 -05:00
|
|
|
let(:project) { create(:project, :repository, skip_disk_validation: true) }
|
2018-10-17 07:33:54 -04:00
|
|
|
let(:gitlab_shell) { Gitlab::Shell.new }
|
|
|
|
let(:hash) { Digest::SHA2.hexdigest(project.id.to_s) }
|
|
|
|
let(:hashed_prefix) { File.join('@hashed', hash[0..1], hash[2..3]) }
|
|
|
|
let(:hashed_path) { File.join(hashed_prefix, hash) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
|
|
|
|
# call. This makes testing a bit easier.
|
|
|
|
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
|
|
|
|
|
|
|
|
stub_application_setting(hashed_storage_enabled: true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'renames a repository' do
|
|
|
|
stub_container_registry_config(enabled: false)
|
|
|
|
|
|
|
|
expect(gitlab_shell).not_to receive(:mv_repository)
|
|
|
|
|
|
|
|
expect_any_instance_of(SystemHooksService)
|
|
|
|
.to receive(:execute_hooks_for)
|
|
|
|
.with(project, :rename)
|
|
|
|
|
|
|
|
expect(project).to receive(:expire_caches_before_rename)
|
|
|
|
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'container registry with images' do
|
|
|
|
let(:container_repository) { create(:container_repository) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
stub_container_registry_config(enabled: true)
|
|
|
|
stub_container_registry_tags(repository: :any, tags: ['tag'])
|
|
|
|
project.container_repositories << container_repository
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'raises a RenameFailedError' do
|
2019-01-16 20:53:50 -05:00
|
|
|
expect { service_execute }
|
2018-10-17 07:33:54 -04:00
|
|
|
.to raise_error(described_class::RenameFailedError)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'gitlab pages' do
|
2020-08-27 11:10:21 -04:00
|
|
|
context 'when the project has pages deployed' do
|
|
|
|
it 'schedules a move of the pages directory' do
|
|
|
|
allow(project).to receive(:pages_deployed?).and_return(true)
|
2018-10-17 07:33:54 -04:00
|
|
|
|
2020-08-27 11:10:21 -04:00
|
|
|
expect(PagesTransferWorker).to receive(:perform_async).with('rename_project', anything)
|
|
|
|
|
|
|
|
service_execute
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the project does not have pages deployed' do
|
|
|
|
it 'does nothing with the pages directory' do
|
|
|
|
allow(project).to receive(:pages_deployed?).and_return(false)
|
|
|
|
|
|
|
|
expect(PagesTransferWorker).not_to receive(:perform_async)
|
|
|
|
expect(Gitlab::PagesTransfer).not_to receive(:new)
|
|
|
|
|
|
|
|
service_execute
|
|
|
|
end
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'attachments' do
|
2019-01-16 20:53:50 -05:00
|
|
|
let(:uploader) { create(:upload, :issuable_upload, :with_file, model: project) }
|
|
|
|
let(:file_uploader) { build(:file_uploader, project: project) }
|
|
|
|
let(:legacy_storage_path) { File.join(file_uploader.root, legacy_storage.disk_path) }
|
|
|
|
let(:hashed_storage_path) { File.join(file_uploader.root, hashed_storage.disk_path) }
|
|
|
|
|
2018-10-17 07:33:54 -04:00
|
|
|
it 'keeps uploads folder location unchanged' do
|
|
|
|
expect_any_instance_of(Gitlab::UploadsTransfer).not_to receive(:rename_project)
|
|
|
|
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when not rolled out' do
|
|
|
|
let(:project) { create(:project, :repository, storage_version: 1, skip_disk_validation: true) }
|
|
|
|
|
2019-01-16 20:53:50 -05:00
|
|
|
it 'moves attachments folder to hashed storage' do
|
|
|
|
expect(File.directory?(legacy_storage_path)).to be_truthy
|
|
|
|
expect(File.directory?(hashed_storage_path)).to be_falsey
|
|
|
|
|
|
|
|
service_execute
|
|
|
|
expect(project.reload.hashed_storage?(:attachments)).to be_truthy
|
2018-10-17 07:33:54 -04:00
|
|
|
|
2019-01-16 20:53:50 -05:00
|
|
|
expect(File.directory?(legacy_storage_path)).to be_falsey
|
|
|
|
expect(File.directory?(hashed_storage_path)).to be_truthy
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'updates project full path in .git/config' do
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2018-10-17 07:33:54 -04:00
|
|
|
|
|
|
|
expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
|
|
|
|
end
|
2018-12-18 14:00:27 -05:00
|
|
|
|
|
|
|
it 'updates storage location' do
|
2019-01-16 20:53:50 -05:00
|
|
|
service_execute
|
2018-12-18 14:00:27 -05:00
|
|
|
|
|
|
|
expect(project.project_repository).to have_attributes(
|
|
|
|
disk_path: project.disk_path,
|
|
|
|
shard_name: project.repository_storage
|
|
|
|
)
|
|
|
|
end
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|
|
|
|
end
|
2019-01-21 22:33:32 -05:00
|
|
|
|
|
|
|
def service_execute
|
|
|
|
# AfterRenameService is called by UpdateService after a successful model.update
|
|
|
|
# the initialization will include before and after paths values
|
2020-10-14 05:08:46 -04:00
|
|
|
project.update!(path: path_after_rename)
|
2019-01-21 22:33:32 -05:00
|
|
|
|
|
|
|
described_class.new(project, path_before: path_before_rename, full_path_before: full_path_before_rename).execute
|
|
|
|
end
|
|
|
|
|
|
|
|
def expect_repository_exist(full_path_with_extension)
|
|
|
|
expect(
|
2019-10-23 05:06:03 -04:00
|
|
|
TestEnv.storage_dir_exists?(
|
2019-01-21 22:33:32 -05:00
|
|
|
project.repository_storage,
|
|
|
|
full_path_with_extension
|
|
|
|
)
|
|
|
|
).to be_truthy
|
|
|
|
end
|
2018-10-17 07:33:54 -04:00
|
|
|
end
|