From c75187df8ce7d376ddc2c7201ce74d45b49fe5d9 Mon Sep 17 00:00:00 2001 From: Travis Miller Date: Sat, 2 Dec 2017 13:49:01 -0600 Subject: [PATCH] Add project export API implementation --- app/models/project.rb | 5 ++- .../projects/import_export/export_service.rb | 2 +- lib/api/api.rb | 1 + lib/api/project_export.rb | 36 +++++++++++++++++++ lib/gitlab/import_export/importer.rb | 2 +- lib/gitlab/import_export/shared.rb | 18 +++++++--- 6 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 lib/api/project_export.rb diff --git a/app/models/project.rb b/app/models/project.rb index 791b69bd9ee..62a3b655ad1 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1560,7 +1560,7 @@ class Project < ActiveRecord::Base def export_path return nil unless namespace.present? || hashed_storage?(:repository) - File.join(Gitlab::ImportExport.storage_path, disk_path) + Gitlab::ImportExport::Shared.new(self).archive_path end def export_project_path @@ -1578,8 +1578,7 @@ class Project < ActiveRecord::Base end def export_in_progress? - shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(disk_path, 'work')) - File.directory?(shared.export_path) + Gitlab::ImportExport::Shared.new(self).active_export_count > 0 end def remove_exports diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index fe4e8ea10bf..e26ce3089bb 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -2,7 +2,7 @@ module Projects module ImportExport class ExportService < BaseService def execute(_options = {}) - @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.disk_path, 'work')) + @shared = Gitlab::ImportExport::Shared.new(project) save_all end diff --git a/lib/api/api.rb b/lib/api/api.rb index 754549f72f0..6c96dccc08a 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -138,6 +138,7 @@ module API mount ::API::PagesDomains mount ::API::Pipelines mount ::API::PipelineSchedules + mount ::API::ProjectExport mount ::API::ProjectImport mount ::API::ProjectHooks mount ::API::Projects diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb new file mode 100644 index 00000000000..8b2c5bedc60 --- /dev/null +++ b/lib/api/project_export.rb @@ -0,0 +1,36 @@ +module API + class ProjectExport < Grape::API + before do + not_found! unless Gitlab::CurrentSettings.current_application_settings.project_export_enabled? + authorize_admin_project + end + + params do + requires :id, type: String, desc: 'The ID of a project' + end + resource :projects, requirements: { id: %r{[^/]+} } do + desc 'Get export status' do + success Entities::ProjectExportStatus + end + get ':id/export' do + present user_project, with: Entities::ProjectExportStatus + end + + desc 'Download export' + get ':id/export/download' do + path = user_project.export_project_path + + render_api_error!('404 Not found or has expired', 404) unless path + + present_file!(path, File.basename(path), 'application/gzip') + end + + desc 'Start export' + post ':id/export' do + user_project.add_export_job(current_user: current_user) + + accepted! + end + end + end +end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index a00795f553e..070dd630c10 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -9,7 +9,7 @@ module Gitlab @archive_file = project.import_source @current_user = project.creator @project = project - @shared = Gitlab::ImportExport::Shared.new(relative_path: path_with_namespace) + @shared = Gitlab::ImportExport::Shared.new(project) end def execute diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index b34cafc6876..fef6cfc08f0 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -1,13 +1,17 @@ module Gitlab module ImportExport class Shared - attr_reader :errors, :opts + attr_reader :errors, :project - def initialize(opts) - @opts = opts + def initialize(project) + @project = project @errors = [] end + def active_export_count + Dir[File.join(archive_path, '*')].count { |name| File.directory?(name) } + end + def export_path @export_path ||= Gitlab::ImportExport.export_path(relative_path: relative_path) end @@ -31,11 +35,15 @@ module Gitlab private def relative_path - File.join(opts[:relative_path], SecureRandom.hex) + File.join(relative_archive_path, SecureRandom.hex) end def relative_archive_path - File.join(opts[:relative_path], '..') + if @project.is_a?(Project) + @project.disk_path + else + @project[:relative_path] + end end def error_out(message, caller) -- GitLab