2017-07-04 20:19:02 -04:00
|
|
|
module Storage
|
|
|
|
module LegacyNamespace
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
|
|
def move_dir
|
|
|
|
if any_project_has_container_registry_tags?
|
|
|
|
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry')
|
|
|
|
end
|
|
|
|
|
2018-03-12 19:55:06 -04:00
|
|
|
parent_was = if parent_changed? && parent_id_was.present?
|
|
|
|
Namespace.find(parent_id_was) # raise NotFound early if needed
|
|
|
|
end
|
|
|
|
|
2017-10-17 06:12:24 -04:00
|
|
|
expires_full_path_cache
|
|
|
|
|
2018-03-13 18:04:00 -04:00
|
|
|
move_repositories
|
2017-07-04 20:19:02 -04:00
|
|
|
|
2018-03-08 17:16:21 -05:00
|
|
|
if parent_changed?
|
2018-03-13 18:04:00 -04:00
|
|
|
former_parent_full_path = parent_was&.full_path
|
2018-03-08 17:16:21 -05:00
|
|
|
parent_full_path = parent&.full_path
|
|
|
|
Gitlab::UploadsTransfer.new.move_namespace(path, former_parent_full_path, parent_full_path)
|
|
|
|
Gitlab::PagesTransfer.new.move_namespace(path, former_parent_full_path, parent_full_path)
|
|
|
|
else
|
|
|
|
Gitlab::UploadsTransfer.new.rename_namespace(full_path_was, full_path)
|
|
|
|
Gitlab::PagesTransfer.new.rename_namespace(full_path_was, full_path)
|
|
|
|
end
|
2017-07-04 20:19:02 -04:00
|
|
|
|
|
|
|
remove_exports!
|
|
|
|
|
|
|
|
# If repositories moved successfully we need to
|
|
|
|
# send update instructions to users.
|
|
|
|
# However we cannot allow rollback since we moved namespace dir
|
|
|
|
# So we basically we mute exceptions in next actions
|
|
|
|
begin
|
|
|
|
send_update_instructions
|
2017-12-21 12:32:08 -05:00
|
|
|
write_projects_repository_config
|
2017-12-19 14:42:51 -05:00
|
|
|
|
2017-07-04 20:19:02 -04:00
|
|
|
true
|
|
|
|
rescue
|
|
|
|
# Returning false does not rollback after_* transaction but gives
|
|
|
|
# us information about failing some of tasks
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Hooks
|
|
|
|
|
2018-04-13 06:57:19 -04:00
|
|
|
# Save the storages before the projects are destroyed to use them on after destroy
|
2017-07-04 20:19:02 -04:00
|
|
|
def prepare_for_destroy
|
2018-04-13 06:57:19 -04:00
|
|
|
old_repository_storages
|
2017-07-04 20:19:02 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2018-03-13 18:04:00 -04:00
|
|
|
def move_repositories
|
2018-04-13 06:57:19 -04:00
|
|
|
# Move the namespace directory in all storages used by member projects
|
|
|
|
repository_storages.each do |repository_storage|
|
2018-03-13 18:04:00 -04:00
|
|
|
# Ensure old directory exists before moving it
|
2018-04-13 06:57:19 -04:00
|
|
|
gitlab_shell.add_namespace(repository_storage, full_path_was)
|
2018-03-13 18:04:00 -04:00
|
|
|
|
|
|
|
# Ensure new directory exists before moving it (if there's a parent)
|
2018-04-13 06:57:19 -04:00
|
|
|
gitlab_shell.add_namespace(repository_storage, parent.full_path) if parent
|
2018-03-13 18:04:00 -04:00
|
|
|
|
2018-04-13 06:57:19 -04:00
|
|
|
unless gitlab_shell.mv_namespace(repository_storage, full_path_was, full_path)
|
2018-03-13 18:04:00 -04:00
|
|
|
|
2018-04-13 06:57:19 -04:00
|
|
|
Rails.logger.error "Exception moving path #{repository_storage} from #{full_path_was} to #{full_path}"
|
2018-03-13 18:04:00 -04:00
|
|
|
|
|
|
|
# if we cannot move namespace directory we should rollback
|
|
|
|
# db changes in order to prevent out of sync between db and fs
|
|
|
|
raise Gitlab::UpdatePathError.new('namespace directory cannot be moved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-13 06:57:19 -04:00
|
|
|
def old_repository_storages
|
|
|
|
@old_repository_storage_paths ||= repository_storages
|
2017-07-04 20:19:02 -04:00
|
|
|
end
|
|
|
|
|
2018-04-13 06:57:19 -04:00
|
|
|
def repository_storages
|
2017-07-04 20:19:02 -04:00
|
|
|
# We need to get the storage paths for all the projects, even the ones that are
|
|
|
|
# pending delete. Unscoping also get rids of the default order, which causes
|
|
|
|
# problems with SELECT DISTINCT.
|
|
|
|
Project.unscoped do
|
2018-04-13 06:57:19 -04:00
|
|
|
all_projects.select('distinct(repository_storage)').to_a.map(&:repository_storage)
|
2017-07-04 20:19:02 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def rm_dir
|
|
|
|
# Remove the namespace directory in all storages paths used by member projects
|
2018-04-13 06:57:19 -04:00
|
|
|
old_repository_storages.each do |repository_storage|
|
2017-07-04 20:19:02 -04:00
|
|
|
# Move namespace directory into trash.
|
|
|
|
# We will remove it later async
|
|
|
|
new_path = "#{full_path}+#{id}+deleted"
|
|
|
|
|
2018-04-13 06:57:19 -04:00
|
|
|
if gitlab_shell.mv_namespace(repository_storage, full_path, new_path)
|
2017-08-01 01:45:04 -04:00
|
|
|
Gitlab::AppLogger.info %Q(Namespace directory "#{full_path}" moved to "#{new_path}")
|
2017-07-04 20:19:02 -04:00
|
|
|
|
|
|
|
# Remove namespace directroy async with delay so
|
|
|
|
# GitLab has time to remove all projects first
|
|
|
|
run_after_commit do
|
2018-04-13 06:57:19 -04:00
|
|
|
GitlabShellWorker.perform_in(5.minutes, :rm_namespace, repository_storage, new_path)
|
2017-07-04 20:19:02 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
remove_exports!
|
|
|
|
end
|
|
|
|
|
2018-01-23 14:03:02 -05:00
|
|
|
def remove_legacy_exports!
|
|
|
|
legacy_export_path = File.join(Gitlab::ImportExport.storage_path, full_path_was)
|
2017-07-04 20:19:02 -04:00
|
|
|
|
2018-01-23 14:03:02 -05:00
|
|
|
FileUtils.rm_rf(legacy_export_path)
|
2017-07-04 20:19:02 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|