This instance will be upgraded to Heptapod 0.27.1 on 2021-12-08 at 22:00 UTC+1 (a few minutes of down time)

Commit 3f7ed550 authored by James Lopez's avatar James Lopez
Browse files

lots of refactoring to reuse import service

parent 472e8aa9d80c
......@@ -12,12 +12,10 @@ def create
return redirect_back_or_default(options: { alert: "You need to upload a GitLab project export archive." })
end
@project = Project.create_from_import_job(current_user_id: current_user.id,
tmp_file: File.expand_path(params[:file].path),
namespace_id: project_params[:namespace_id],
project_path: project_params[:path])
@project = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute
@project = Gitlab::GitlabImport::ProjectCreator.new(Namespace.find(project_params[:namespace_id]),
current_user,
File.expand_path(params[:file].path),
project_params[:path]).execute
flash[:notice] = "The project import has been started."
......
......@@ -190,7 +190,7 @@ def export
redirect_to(
edit_project_path(@project),
notice: "Project export successfully started"
notice: "Project export successfully started."
)
end
......
......@@ -492,6 +492,10 @@ def safe_import_url
Gitlab::UrlSanitizer.new(import_url).masked_url
end
def gitlab_project_import?
import_type == 'gitlab_project'
end
def check_limit
unless creator.can_create_project? or namespace.kind == 'group'
projects_limit = creator.projects_limit
......
......@@ -45,10 +45,6 @@ def for_commit?
target_type == "Commit"
end
def for_project?
target_type == "Project"
end
# override to return commits, which are not active record
def target
if for_commit?
......
......@@ -52,9 +52,11 @@ def execute
save_project_and_import_data(import_data)
@project.import_url = download_export_namespace_project_path(@project.namespace, @project) if @project.gitlab_project_import?
@project.import_start if @project.import?
after_create_actions if @project.persisted?
after_create_actions if @project.persisted? && !@project.gitlab_project_import?
if @project.errors.empty?
@project.add_import_job if @project.import?
......
......@@ -9,7 +9,8 @@ class Error < StandardError; end
'fogbugz',
'gitlab',
'github',
'google_code'
'google_code',
'gitlab_project'
]
def execute
......@@ -37,7 +38,7 @@ def create_repository
def import_repository
begin
gitlab_shell.import_repository(project.path_with_namespace, project.import_url)
gitlab_shell.import_repository(project.path_with_namespace, project.import_url) unless @project.gitlab_project_import?
rescue Gitlab::Shell::Error => e
raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}"
end
......@@ -58,6 +59,8 @@ def has_importer?
end
def importer
return Gitlab::ImportExport::Importer if @project.gitlab_project_import?
class_name = "Gitlab::#{project.import_type.camelize}Import::Importer"
class_name.constantize.new(project)
end
......
......@@ -120,6 +120,19 @@
= link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project),
method: :post, class: "btn btn-save"
%hr
.row.prepend-top-default
.col-lg-3
%h4.prepend-top-0
Export project
%p.append-bottom-0
%p
Generates a compressed export file of the project and sends a link to download the export.
.col-lg-9
= link_to 'Generate new export', export_namespace_project_path(@project.namespace, @project),
method: :post, class: "btn btn-default"
%hr
- if can? current_user, :archive_project, @project
.row.prepend-top-default
.col-lg-3
......
......@@ -7,10 +7,10 @@ class ProjectImportWorker
def perform(current_user_id, tmp_file, namespace_id, path)
current_user = User.find(current_user_id)
project = Gitlab::ImportExport::ImportService.execute(archive_file: tmp_file,
owner: current_user,
namespace_id: namespace_id,
project_path: path)
project = Gitlab::ImportExport::Importer.execute(archive_file: tmp_file,
owner: current_user,
namespace_id: namespace_id,
project_path: path)
if project
project.repository.after_import
else
......
......@@ -3,24 +3,21 @@ module GitlabImport
class ProjectCreator
attr_reader :repo, :namespace, :current_user, :session_data
def initialize(repo, namespace, current_user, session_data)
@repo = repo
@namespace = namespace
def initialize(namespace_id, current_user, file, project_path)
@namespace_id = namespace_id
@current_user = current_user
@session_data = session_data
@file = file
@project_path = project_path
end
def execute
::Projects::CreateService.new(
current_user,
name: repo["name"],
path: repo["path"],
description: repo["description"],
namespace_id: namespace.id,
visibility_level: repo["visibility_level"],
import_type: "gitlab",
import_source: repo["path_with_namespace"],
import_url: repo["http_url_to_repo"].sub("://", "://oauth2:#{@session_data[:gitlab_access_token]}@")
name: @project_path,
path: @project_path,
namespace_id: namespace_id,
import_type: "gitlab_project",
import_source: @file
).execute
end
end
......
module Gitlab
module ImportExport
class FileImporter
include Gitlab::ImportExport::CommandLineUtil
def self.import(*args)
new(*args).import
end
def initialize(archive_file:, shared:)
@archive_file = archive_file
@shared = shared
end
def import
FileUtils.mkdir_p(@shared.export_path)
decompress_archive
rescue => e
@shared.error(e)
false
end
private
def decompress_archive
untar_zxf(archive: @archive_file, dir: @shared.export_path)
end
end
end
end
......@@ -30,8 +30,6 @@ project_tree:
# Only include the following attributes for the models specified.
included_attributes:
project:
- :name
- :path
- :description
- :issues_enabled
- :merge_requests_enabled
......
module Gitlab
module ImportExport
class ImportService
def self.execute(*args)
new(*args).execute
end
def initialize(archive_file:, owner:, namespace_id:, project_path:)
@archive_file = archive_file
@current_user = owner
@namespace = Namespace.find(namespace_id)
@shared = Gitlab::ImportExport::Shared.new(relative_path: path_with_namespace(project_path), project_path: project_path)
end
def execute
Gitlab::ImportExport::Importer.import(archive_file: @archive_file,
shared: @shared)
if check_version! && [project_tree, repo_restorer, wiki_restorer, uploads_restorer].all?(&:restore)
project_tree.project
else
project_tree.project.destroy if project_tree.project
nil
end
end
private
def check_version!
Gitlab::ImportExport::VersionChecker.check!(shared: @shared)
end
def project_tree
@project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(user: @current_user,
shared: @shared,
namespace_id: @namespace.id)
end
def repo_restorer
Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path,
shared: @shared,
project: project_tree.project)
end
def wiki_restorer
Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path,
shared: @shared,
project: ProjectWiki.new(project_tree.project),
wiki: true)
end
def uploads_restorer
Gitlab::ImportExport::UploadsRestorer.new(project: project_tree.project, shared: @shared)
end
def path_with_namespace(project_path)
File.join(@namespace.path, project_path)
end
def repo_path
File.join(@shared.export_path, 'project.bundle')
end
def wiki_repo_path
File.join(@shared.export_path, 'project.wiki.bundle')
end
def attributes_for_todo
{ user_id: @current_user.id,
project_id: project_tree.project.id,
target_type: 'Project',
target: project_tree.project,
action: Todo::IMPORTED,
author_id: @current_user.id,
state: :pending,
target_id: project_tree.project.id
}
end
end
end
end
module Gitlab
module ImportExport
class Importer
include Gitlab::ImportExport::CommandLineUtil
def self.import(*args)
new(*args).import
def self.execute(*args)
new(*args).execute
end
def initialize(archive_file:, shared:)
@archive_file = archive_file
@shared = shared
def initialize(project)
@archive_file = project.import_source
@current_user = project.creator
@shared = Gitlab::ImportExport::Shared.new(relative_path: path_with_namespace(@project.path))
end
def import
FileUtils.mkdir_p(@shared.export_path)
decompress_archive
rescue => e
@shared.error(e)
false
def execute
Gitlab::ImportExport::FileImporter.import(archive_file: @archive_file,
shared: @shared)
if check_version! && [project_tree, repo_restorer, wiki_restorer, uploads_restorer].all?(&:restore)
project_tree.project
else
project_tree.project.destroy if project_tree.project
nil
end
end
private
def decompress_archive
untar_zxf(archive: @archive_file, dir: @shared.export_path)
def check_version!
Gitlab::ImportExport::VersionChecker.check!(shared: @shared)
end
def project_tree
@project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(user: @current_user,
shared: @shared,
project: @project)
end
def repo_restorer
Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path,
shared: @shared,
project: project_tree.project)
end
def wiki_restorer
Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path,
shared: @shared,
project: ProjectWiki.new(project_tree.project),
wiki: true)
end
def uploads_restorer
Gitlab::ImportExport::UploadsRestorer.new(project: project_tree.project, shared: @shared)
end
def path_with_namespace(project_path)
File.join(@namespace.path, project_path)
end
def repo_path
File.join(@shared.export_path, 'project.bundle')
end
def wiki_repo_path
File.join(@shared.export_path, 'project.wiki.bundle')
end
def attributes_for_todo
{ user_id: @current_user.id,
project_id: project_tree.project.id,
target_type: 'Project',
target: project_tree.project,
action: Todo::IMPORTED,
author_id: @current_user.id,
state: :pending,
target_id: project_tree.project.id
}
end
end
end
......
module Gitlab
module ImportExport
module ProjectFactory
extend self
def create(project_params:, user:, namespace_id:)
project = Project.new(project_params.except('id'))
project.creator = user
check_namespace(namespace_id, project, user)
end
def check_namespace(namespace_id, project, user)
if namespace_id
# Find matching namespace and check if it allowed
# for current user if namespace_id passed.
if allowed_namespace?(user, namespace_id)
project.namespace_id = namespace_id
else
project.namespace_id = nil
deny_namespace(project)
end
else
# Set current user namespace if namespace_id is nil
project.namespace_id = user.namespace_id
end
project
end
private
def allowed_namespace?(user, namespace_id)
namespace = Namespace.find_by(id: namespace_id)
user.can?(:create_projects, namespace)
end
def deny_namespace(project)
project.errors.add(:namespace, "is not valid")
end
end
end
end
......@@ -2,12 +2,11 @@ module Gitlab
module ImportExport
class ProjectTreeRestorer
def initialize(user:, shared:, namespace_id:)
def initialize(user:, shared:, project:)
@path = File.join(shared.export_path, 'project.json')
@user = user
@project_path = shared.opts[:project_path]
@namespace_id = namespace_id
@shared = shared
@project = project
end
def restore
......@@ -21,7 +20,7 @@ def restore
end
def project
@project ||= create_project
@restored_project ||= restore_project
end
private
......@@ -57,14 +56,10 @@ def default_relation_list
end
end
def create_project
def restore_project
project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) }
project = Gitlab::ImportExport::ProjectFactory.create(
project_params: project_params, user: @user, namespace_id: @namespace_id)
project.path = @project_path
project.name = @project_path
project.save!
project
@project.update(project_params)
@project
end
# Given a relation hash containing one or more models and its relationships,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment