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

lots of refactoring to reuse import service

parent 1ea44ee7
...@@ -12,12 +12,10 @@ class Import::GitlabProjectsController < Import::BaseController ...@@ -12,12 +12,10 @@ class Import::GitlabProjectsController < Import::BaseController
return redirect_back_or_default(options: { alert: "You need to upload a GitLab project export archive." }) return redirect_back_or_default(options: { alert: "You need to upload a GitLab project export archive." })
end end
@project = Project.create_from_import_job(current_user_id: current_user.id, @project = Gitlab::GitlabImport::ProjectCreator.new(Namespace.find(project_params[:namespace_id]),
tmp_file: File.expand_path(params[:file].path), current_user,
namespace_id: project_params[:namespace_id], File.expand_path(params[:file].path),
project_path: project_params[:path]) project_params[:path]).execute
@project = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute
flash[:notice] = "The project import has been started." flash[:notice] = "The project import has been started."
......
...@@ -190,7 +190,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -190,7 +190,7 @@ class ProjectsController < Projects::ApplicationController
redirect_to( redirect_to(
edit_project_path(@project), edit_project_path(@project),
notice: "Project export successfully started" notice: "Project export successfully started."
) )
end end
......
...@@ -492,6 +492,10 @@ class Project < ActiveRecord::Base ...@@ -492,6 +492,10 @@ class Project < ActiveRecord::Base
Gitlab::UrlSanitizer.new(import_url).masked_url Gitlab::UrlSanitizer.new(import_url).masked_url
end end
def gitlab_project_import?
import_type == 'gitlab_project'
end
def check_limit def check_limit
unless creator.can_create_project? or namespace.kind == 'group' unless creator.can_create_project? or namespace.kind == 'group'
projects_limit = creator.projects_limit projects_limit = creator.projects_limit
......
...@@ -45,10 +45,6 @@ class Todo < ActiveRecord::Base ...@@ -45,10 +45,6 @@ class Todo < ActiveRecord::Base
target_type == "Commit" target_type == "Commit"
end end
def for_project?
target_type == "Project"
end
# override to return commits, which are not active record # override to return commits, which are not active record
def target def target
if for_commit? if for_commit?
......
...@@ -52,9 +52,11 @@ module Projects ...@@ -52,9 +52,11 @@ module Projects
save_project_and_import_data(import_data) 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? @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? if @project.errors.empty?
@project.add_import_job if @project.import? @project.add_import_job if @project.import?
......
...@@ -9,7 +9,8 @@ module Projects ...@@ -9,7 +9,8 @@ module Projects
'fogbugz', 'fogbugz',
'gitlab', 'gitlab',
'github', 'github',
'google_code' 'google_code',
'gitlab_project'
] ]
def execute def execute
...@@ -37,7 +38,7 @@ module Projects ...@@ -37,7 +38,7 @@ module Projects
def import_repository def import_repository
begin 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 rescue Gitlab::Shell::Error => e
raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}" raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}"
end end
...@@ -58,6 +59,8 @@ module Projects ...@@ -58,6 +59,8 @@ module Projects
end end
def importer def importer
return Gitlab::ImportExport::Importer if @project.gitlab_project_import?
class_name = "Gitlab::#{project.import_type.camelize}Import::Importer" class_name = "Gitlab::#{project.import_type.camelize}Import::Importer"
class_name.constantize.new(project) class_name.constantize.new(project)
end end
......
...@@ -120,6 +120,19 @@ ...@@ -120,6 +120,19 @@
= link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project), = link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project),
method: :post, class: "btn btn-save" method: :post, class: "btn btn-save"
%hr %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 - if can? current_user, :archive_project, @project
.row.prepend-top-default .row.prepend-top-default
.col-lg-3 .col-lg-3
......
...@@ -7,10 +7,10 @@ class ProjectImportWorker ...@@ -7,10 +7,10 @@ class ProjectImportWorker
def perform(current_user_id, tmp_file, namespace_id, path) def perform(current_user_id, tmp_file, namespace_id, path)
current_user = User.find(current_user_id) current_user = User.find(current_user_id)
project = Gitlab::ImportExport::ImportService.execute(archive_file: tmp_file, project = Gitlab::ImportExport::Importer.execute(archive_file: tmp_file,
owner: current_user, owner: current_user,
namespace_id: namespace_id, namespace_id: namespace_id,
project_path: path) project_path: path)
if project if project
project.repository.after_import project.repository.after_import
else else
......
...@@ -3,24 +3,21 @@ module Gitlab ...@@ -3,24 +3,21 @@ module Gitlab
class ProjectCreator class ProjectCreator
attr_reader :repo, :namespace, :current_user, :session_data attr_reader :repo, :namespace, :current_user, :session_data
def initialize(repo, namespace, current_user, session_data) def initialize(namespace_id, current_user, file, project_path)
@repo = repo @namespace_id = namespace_id
@namespace = namespace
@current_user = current_user @current_user = current_user
@session_data = session_data @file = file
@project_path = project_path
end end
def execute def execute
::Projects::CreateService.new( ::Projects::CreateService.new(
current_user, current_user,
name: repo["name"], name: @project_path,
path: repo["path"], path: @project_path,
description: repo["description"], namespace_id: namespace_id,
namespace_id: namespace.id, import_type: "gitlab_project",
visibility_level: repo["visibility_level"], import_source: @file
import_type: "gitlab",
import_source: repo["path_with_namespace"],
import_url: repo["http_url_to_repo"].sub("://", "://oauth2:#{@session_data[:gitlab_access_token]}@")
).execute ).execute
end end
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: ...@@ -30,8 +30,6 @@ project_tree:
# Only include the following attributes for the models specified. # Only include the following attributes for the models specified.
included_attributes: included_attributes:
project: project:
- :name
- :path
- :description - :description
- :issues_enabled - :issues_enabled
- :merge_requests_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 Gitlab
module ImportExport module ImportExport
class Importer class Importer
include Gitlab::ImportExport::CommandLineUtil
def self.import(*args) def self.execute(*args)
new(*args).import new(*args).execute
end end
def initialize(archive_file:, shared:) def initialize(project)
@archive_file = archive_file @archive_file = project.import_source
@shared = shared @current_user = project.creator
@shared = Gitlab::ImportExport::Shared.new(relative_path: path_with_namespace(@project.path))
end end
def import def execute
FileUtils.mkdir_p(@shared.export_path) Gitlab::ImportExport::FileImporter.import(archive_file: @archive_file,
decompress_archive shared: @shared)
rescue => e if check_version! && [project_tree, repo_restorer, wiki_restorer, uploads_restorer].all?(&:restore)
@shared.error(e) project_tree.project
false else
project_tree.project.destroy if project_tree.project
nil
end
end end
private private
def decompress_archive def check_version!
untar_zxf(archive: @archive_file, dir: @shared.export_path) 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 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 ...@@ -2,12 +2,11 @@ module Gitlab
module ImportExport module ImportExport
class ProjectTreeRestorer class ProjectTreeRestorer
def initialize(user:, shared:, namespace_id:) def initialize(user:, shared:, project:)
@path = File.join(shared.export_path, 'project.json') @path = File.join(shared.export_path, 'project.json')
@user = user @user = user
@project_path = shared.opts[:project_path]
@namespace_id = namespace_id
@shared = shared @shared = shared
@project = project
end end
def restore def restore
...@@ -21,7 +20,7 @@ module Gitlab ...@@ -21,7 +20,7 @@ module Gitlab
end end
def project def project
@project ||= create_project @restored_project ||= restore_project
end end
private private
...@@ -57,14 +56,10 @@ module Gitlab ...@@ -57,14 +56,10 @@ module Gitlab
end end
end end
def create_project def restore_project
project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) }
project = Gitlab::ImportExport::ProjectFactory.create( @project.update(project_params)
project_params: project_params, user: @user, namespace_id: @namespace_id) @project
project.path = @project_path
project.name = @project_path
project.save!
project
end end
# Given a relation hash containing one or more models and its relationships, # 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