2019-01-15 03:37:27 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Projects
|
|
|
|
module HashedStorage
|
2019-03-01 06:57:11 +00:00
|
|
|
# Returned when repository can't be made read-only because there is already a git transfer in progress
|
|
|
|
RepositoryInUseError = Class.new(StandardError)
|
2019-01-15 03:37:27 +00:00
|
|
|
|
|
|
|
class BaseRepositoryService < BaseService
|
|
|
|
include Gitlab::ShellAdapter
|
|
|
|
|
2020-05-13 18:08:47 +00:00
|
|
|
attr_reader :old_disk_path, :new_disk_path, :old_storage_version,
|
|
|
|
:logger, :move_wiki, :move_design
|
2019-01-15 03:37:27 +00:00
|
|
|
|
2019-11-14 21:06:14 +00:00
|
|
|
def initialize(project:, old_disk_path:, logger: nil)
|
2019-01-15 03:37:27 +00:00
|
|
|
@project = project
|
2019-01-25 18:05:26 +00:00
|
|
|
@logger = logger || Gitlab::AppLogger
|
2019-01-15 03:37:27 +00:00
|
|
|
@old_disk_path = old_disk_path
|
|
|
|
@move_wiki = has_wiki?
|
2020-05-13 18:08:47 +00:00
|
|
|
@move_design = has_design?
|
2019-01-15 03:37:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def has_wiki?
|
2019-10-09 09:06:19 +00:00
|
|
|
gitlab_shell.repository_exists?(project.repository_storage, "#{old_wiki_disk_path}.git")
|
2019-01-15 03:37:27 +00:00
|
|
|
end
|
|
|
|
|
2020-05-13 18:08:47 +00:00
|
|
|
def has_design?
|
|
|
|
gitlab_shell.repository_exists?(project.repository_storage, "#{old_design_disk_path}.git")
|
|
|
|
end
|
|
|
|
|
2019-01-15 03:37:27 +00:00
|
|
|
def move_repository(from_name, to_name)
|
2019-10-09 09:06:19 +00:00
|
|
|
from_exists = gitlab_shell.repository_exists?(project.repository_storage, "#{from_name}.git")
|
|
|
|
to_exists = gitlab_shell.repository_exists?(project.repository_storage, "#{to_name}.git")
|
2019-01-15 03:37:27 +00:00
|
|
|
|
|
|
|
# If we don't find the repository on either original or target we should log that as it could be an issue if the
|
|
|
|
# project was not originally empty.
|
|
|
|
if !from_exists && !to_exists
|
|
|
|
logger.warn "Can't find a repository on either source or target paths for #{project.full_path} (ID=#{project.id}) ..."
|
2019-02-22 08:12:06 +00:00
|
|
|
|
2019-02-27 05:08:34 +00:00
|
|
|
# We return true so we still reflect the change in the database.
|
|
|
|
# Next time the repository is (re)created it will be under the new storage layout
|
2019-02-22 08:12:06 +00:00
|
|
|
return true
|
2019-01-15 03:37:27 +00:00
|
|
|
elsif !from_exists
|
|
|
|
# Repository have been moved already.
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2020-04-06 12:10:44 +00:00
|
|
|
gitlab_shell.mv_repository(project.repository_storage, from_name, to_name).tap do |moved|
|
|
|
|
if moved
|
|
|
|
logger.info("Repository moved from '#{from_name}' to '#{to_name}' (PROJECT_ID=#{project.id})")
|
|
|
|
else
|
|
|
|
logger.error("Repository cannot be moved from '#{from_name}' to '#{to_name}' (PROJECT_ID=#{project.id})")
|
|
|
|
end
|
|
|
|
end
|
2019-01-15 03:37:27 +00:00
|
|
|
end
|
|
|
|
|
2019-12-11 06:07:52 +00:00
|
|
|
def move_repositories
|
|
|
|
result = move_repository(old_disk_path, new_disk_path)
|
|
|
|
project.reload_repository!
|
|
|
|
|
|
|
|
if move_wiki
|
|
|
|
result &&= move_repository(old_wiki_disk_path, new_wiki_disk_path)
|
|
|
|
project.clear_memoization(:wiki)
|
|
|
|
end
|
|
|
|
|
2020-05-13 18:08:47 +00:00
|
|
|
if move_design
|
|
|
|
result &&= move_repository(old_design_disk_path, new_design_disk_path)
|
|
|
|
project.clear_memoization(:design_repository)
|
|
|
|
end
|
|
|
|
|
2019-12-11 06:07:52 +00:00
|
|
|
result
|
|
|
|
end
|
|
|
|
|
2019-01-15 03:37:27 +00:00
|
|
|
def rollback_folder_move
|
|
|
|
move_repository(new_disk_path, old_disk_path)
|
2019-12-11 06:07:52 +00:00
|
|
|
move_repository(new_wiki_disk_path, old_wiki_disk_path)
|
2020-05-13 18:08:47 +00:00
|
|
|
move_repository(new_design_disk_path, old_design_disk_path) if move_design
|
2019-01-15 03:37:27 +00:00
|
|
|
end
|
2019-03-01 06:57:11 +00:00
|
|
|
|
|
|
|
def try_to_set_repository_read_only!
|
2020-10-21 06:09:17 +00:00
|
|
|
project.set_repository_read_only!
|
|
|
|
rescue Project::RepositoryReadOnlyError => err
|
|
|
|
migration_error = "Target repository '#{old_disk_path}' cannot be made read-only: #{err.message}"
|
|
|
|
logger.error migration_error
|
2019-03-01 06:57:11 +00:00
|
|
|
|
2020-10-21 06:09:17 +00:00
|
|
|
raise RepositoryInUseError, migration_error
|
2019-03-01 06:57:11 +00:00
|
|
|
end
|
2019-12-11 06:07:52 +00:00
|
|
|
|
|
|
|
def wiki_path_suffix
|
|
|
|
@wiki_path_suffix ||= Gitlab::GlRepository::WIKI.path_suffix
|
|
|
|
end
|
|
|
|
|
|
|
|
def old_wiki_disk_path
|
|
|
|
@old_wiki_disk_path ||= "#{old_disk_path}#{wiki_path_suffix}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def new_wiki_disk_path
|
|
|
|
@new_wiki_disk_path ||= "#{new_disk_path}#{wiki_path_suffix}"
|
|
|
|
end
|
2020-05-13 18:08:47 +00:00
|
|
|
|
|
|
|
def design_path_suffix
|
|
|
|
@design_path_suffix ||= ::Gitlab::GlRepository::DESIGN.path_suffix
|
|
|
|
end
|
|
|
|
|
|
|
|
def old_design_disk_path
|
|
|
|
@old_design_disk_path ||= "#{old_disk_path}#{design_path_suffix}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def new_design_disk_path
|
|
|
|
@new_design_disk_path ||= "#{new_disk_path}#{design_path_suffix}"
|
|
|
|
end
|
2019-01-15 03:37:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|