gitlab-org--gitlab-foss/app/services/projects/after_rename_service.rb
Yorick Peterse 4b9c17f196
Move Project#rename_repo to a service class
This moves the logic of Project#rename_repo and all methods _only_ used
by this method into a new service class: Projects::AfterRenameService.
By moving this code into a separate service class we can more easily
refactor it, and we also get rid of some RuboCop "disable" statements
automatically.

During the refactoring of this code, I removed most of the explicit
logging using Gitlab::AppLogger. The data that was logged would not be
useful when debugging renaming issues, as it does not add any value on
top of data provided by users.

I also removed a variety of comments that either mentioned something the
code does in literal form, or contained various grammatical errors.
Instead we now resort to more clearly named methods, removing the need
for code comments.

This method was chosen based on analysis in
https://gitlab.com/gitlab-org/release/framework/issues/28. In this issue
we determined this method has seen a total of 293 lines being changed in
it. We also noticed that RuboCop determined the ABC size
(https://www.softwarerenovation.com/ABCMetric.pdf) was too great.
2018-10-22 15:12:46 +02:00

135 lines
3.5 KiB
Ruby

# frozen_string_literal: true
module Projects
# Service class for performing operations that should take place after a
# project has been renamed.
#
# Example usage:
#
# project = Project.find(42)
#
# project.update(...)
#
# Projects::AfterRenameService.new(project).execute
class AfterRenameService
attr_reader :project, :full_path_before, :full_path_after, :path_before
RenameFailedError = Class.new(StandardError)
# @param [Project] project The Project of the repository to rename.
def initialize(project)
@project = project
# The full path of the namespace + project, before the rename took place.
@full_path_before = project.full_path_was
# The full path of the namespace + project, after the rename took place.
@full_path_after = project.build_full_path
# The path of just the project, before the rename took place.
@path_before = project.path_was
end
def execute
first_ensure_no_registry_tags_are_present
expire_caches_before_rename
rename_or_migrate_repository!
send_move_instructions
execute_system_hooks
update_repository_configuration
rename_transferred_documents
log_completion
end
def first_ensure_no_registry_tags_are_present
return unless project.has_container_registry_tags?
raise RenameFailedError.new(
"Project #{full_path_before} cannot be renamed because images are " \
"present in its container registry"
)
end
def expire_caches_before_rename
project.expire_caches_before_rename(full_path_before)
end
def rename_or_migrate_repository!
success =
if migrate_to_hashed_storage?
::Projects::HashedStorageMigrationService
.new(project, full_path_before)
.execute
else
project.storage.rename_repo
end
rename_failed! unless success
end
def send_move_instructions
return unless send_move_instructions?
project.send_move_instructions(full_path_before)
end
def execute_system_hooks
project.old_path_with_namespace = full_path_before
SystemHooksService.new.execute_hooks_for(project, :rename)
end
def update_repository_configuration
project.reload_repository!
project.write_repository_config
end
def rename_transferred_documents
if rename_uploads?
Gitlab::UploadsTransfer
.new
.rename_project(path_before, project_path, namespace_full_path)
end
Gitlab::PagesTransfer
.new
.rename_project(path_before, project_path, namespace_full_path)
end
def log_completion
Gitlab::AppLogger.info(
"Project #{project.id} has been renamed from " \
"#{full_path_before} to #{full_path_after}"
)
end
def migrate_to_hashed_storage?
Gitlab::CurrentSettings.hashed_storage_enabled? &&
project.storage_upgradable? &&
Feature.disabled?(:skip_hashed_storage_upgrade)
end
def send_move_instructions?
!project.import_started?
end
def rename_uploads?
!project.hashed_storage?(:attachments)
end
def project_path
project.path
end
def namespace_full_path
project.namespace.full_path
end
def rename_failed!
error = "Repository #{full_path_before} could not be renamed to #{full_path_after}"
Gitlab::AppLogger.error(error)
raise RenameFailedError.new(error)
end
end
end