debian-mirror-gitlab/app/services/projects/import_service.rb

163 lines
4.8 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2016-04-02 18:10:28 +05:30
module Projects
class ImportService < BaseService
2017-08-17 22:00:37 +05:30
Error = Class.new(StandardError)
2020-05-24 23:13:21 +05:30
PermissionError = Class.new(StandardError)
2016-04-02 18:10:28 +05:30
2018-03-17 18:26:18 +05:30
# Returns true if this importer is supposed to perform its work in the
# background.
#
# This method will only return `true` if async importing is explicitly
# supported by an importer class (`Gitlab::GithubImport::ParallelImporter`
# for example).
def async?
has_importer? && !!importer_class.try(:async?)
end
2016-04-02 18:10:28 +05:30
def execute
2021-11-18 22:05:49 +05:30
track_start_import
2018-03-17 18:26:18 +05:30
add_repository_to_project
2016-04-02 18:10:28 +05:30
2018-11-08 19:23:39 +05:30
download_lfs_objects
2016-04-02 18:10:28 +05:30
import_data
2020-05-24 23:13:21 +05:30
after_execute_hook
2016-04-02 18:10:28 +05:30
success
2021-11-18 22:05:49 +05:30
rescue Gitlab::UrlBlocker::BlockedUrlError, StandardError => e
Gitlab::Import::ImportFailureService.track(
project_id: project.id,
error_source: self.class.name,
exception: e,
metrics: true
)
2019-02-15 15:39:39 +05:30
2019-02-02 18:00:53 +05:30
message = Projects::ImportErrorFilter.filter_message(e.message)
2021-11-18 22:05:49 +05:30
error(s_("ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}") %
{ project_safe_import_url: project.safe_import_url, project_full_path: project.full_path, message: message })
2016-04-02 18:10:28 +05:30
end
2020-05-24 23:13:21 +05:30
protected
def extra_attributes_for_measurement
{
current_user: current_user&.name,
project_full_path: project&.full_path,
import_type: project&.import_type,
file_path: project&.import_source
}
end
2016-04-02 18:10:28 +05:30
private
2020-05-24 23:13:21 +05:30
def after_execute_hook
# Defined in EE::Projects::ImportService
end
2021-11-18 22:05:49 +05:30
def track_start_import
has_importer? && importer_class.try(:track_start_import, project)
end
2016-06-22 15:30:34 +05:30
def add_repository_to_project
2018-03-17 18:26:18 +05:30
if project.external_import? && !unknown_url?
2018-05-09 12:01:36 +05:30
begin
2018-11-08 19:23:39 +05:30
Gitlab::UrlBlocker.validate!(project.import_url, ports: Project::VALID_IMPORT_PORTS)
2018-05-09 12:01:36 +05:30
rescue Gitlab::UrlBlocker::BlockedUrlError => e
2019-07-31 22:56:46 +05:30
raise e, s_("ImportProjects|Blocked import URL: %{message}") % { message: e.message }
2018-05-09 12:01:36 +05:30
end
2018-03-17 18:26:18 +05:30
end
# We should skip the repository for a GitHub import or GitLab project import,
# because these importers fetch the project repositories for us.
2018-11-08 19:23:39 +05:30
return if importer_imports_repository?
2018-03-17 18:26:18 +05:30
2016-06-22 15:30:34 +05:30
if unknown_url?
# In this case, we only want to import issues, not a repository.
create_repository
2016-11-03 12:29:30 +05:30
elsif !project.repository_exists?
2016-06-22 15:30:34 +05:30
import_repository
end
end
2016-04-02 18:10:28 +05:30
def create_repository
unless project.create_repository
2019-07-31 22:56:46 +05:30
raise Error, s_('ImportProjects|The repository could not be created.')
2016-04-02 18:10:28 +05:30
end
end
def import_repository
2020-03-13 15:44:24 +05:30
refmap = importer_class.try(:refmap) if has_importer?
2016-11-03 12:29:30 +05:30
2020-03-13 15:44:24 +05:30
if refmap
project.ensure_repository
project.repository.fetch_as_mirror(project.import_url, refmap: refmap)
else
2020-04-08 14:13:33 +05:30
project.repository.import_repository(project.import_url)
2016-04-02 18:10:28 +05:30
end
2020-04-08 14:13:33 +05:30
rescue ::Gitlab::Git::CommandError => e
2020-03-13 15:44:24 +05:30
# Expire cache to prevent scenarios such as:
# 1. First import failed, but the repo was imported successfully, so +exists?+ returns true
# 2. Retried import, repo is broken or not imported but +exists?+ still returns true
project.repository.expire_content_cache if project.repository_exists?
raise Error, e.message
2016-04-02 18:10:28 +05:30
end
2018-11-08 19:23:39 +05:30
def download_lfs_objects
# In this case, we only want to import issues
return if unknown_url?
# If it has its own repository importer, it has to implements its own lfs import download
return if importer_imports_repository?
return unless project.lfs_enabled?
2019-07-31 22:56:46 +05:30
result = Projects::LfsPointers::LfsImportService.new(project).execute
2018-11-08 19:23:39 +05:30
2019-07-31 22:56:46 +05:30
if result[:status] == :error
# To avoid aborting the importing process, we silently fail
# if any exception raises.
Gitlab::AppLogger.error("The Lfs import process failed. #{result[:message]}")
2018-11-08 19:23:39 +05:30
end
end
2016-04-02 18:10:28 +05:30
def import_data
return unless has_importer?
2017-08-17 22:00:37 +05:30
project.repository.expire_content_cache unless project.gitlab_project_import?
2016-06-02 11:05:42 +05:30
2016-04-02 18:10:28 +05:30
unless importer.execute
2019-07-31 22:56:46 +05:30
raise Error, s_('ImportProjects|The remote data could not be imported.')
2016-04-02 18:10:28 +05:30
end
end
2018-03-17 18:26:18 +05:30
def importer_class
@importer_class ||= Gitlab::ImportSources.importer(project.import_type)
end
2016-04-02 18:10:28 +05:30
def has_importer?
2017-08-17 22:00:37 +05:30
Gitlab::ImportSources.importer_names.include?(project.import_type)
2016-04-02 18:10:28 +05:30
end
def importer
2018-03-17 18:26:18 +05:30
importer_class.new(project)
2016-04-02 18:10:28 +05:30
end
def unknown_url?
project.import_url == Project::UNKNOWN_IMPORT_URL
end
2018-11-08 19:23:39 +05:30
def importer_imports_repository?
has_importer? && importer_class.try(:imports_repository?)
end
2016-04-02 18:10:28 +05:30
end
end
2020-05-24 23:13:21 +05:30
2021-06-08 01:23:25 +05:30
Projects::ImportService.prepend_mod_with('Projects::ImportService')
2020-05-24 23:13:21 +05:30
# Measurable should be at the bottom of the ancestor chain, so it will measure execution of EE::Projects::ImportService as well
Projects::ImportService.prepend(Measurable)