summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/services/projects/import_export.rb23
-rw-r--r--app/services/projects/import_export/export_service.rb15
-rw-r--r--app/services/projects/import_export/project_tree_saver.rb42
-rw-r--r--spec/services/projects/import_export/project_tree_saver_spec.rb83
4 files changed, 163 insertions, 0 deletions
diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb
new file mode 100644
index 00000000000..f87b10390a5
--- /dev/null
+++ b/app/services/projects/import_export.rb
@@ -0,0 +1,23 @@
+module Projects
+ module ImportExport
+ extend self
+
+ def export_path(project_name:)
+ File.join(storage_path, "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_gitlab_export_#{project_name}")
+ end
+
+ def project_atts
+ %i(id name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived)
+ end
+
+ def project_tree
+ %i(issues merge_requests labels milestones snippets releases events commit_statuses)
+ end
+
+ private
+
+ def storage_path
+ File.join(Settings.shared['path'], 'tmp/project_exports')
+ end
+ end
+end
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
new file mode 100644
index 00000000000..c89dd3d12ed
--- /dev/null
+++ b/app/services/projects/import_export/export_service.rb
@@ -0,0 +1,15 @@
+module Projects
+ module ImportExport
+ class ExportService < BaseService
+ def execute(options = {})
+ save_project_tree
+ end
+
+ private
+
+ def save_project_tree
+ Projects::ImportExport::ProjectTreeSaver.save(project: project)
+ end
+ end
+ end
+end
diff --git a/app/services/projects/import_export/project_tree_saver.rb b/app/services/projects/import_export/project_tree_saver.rb
new file mode 100644
index 00000000000..4801c791ffe
--- /dev/null
+++ b/app/services/projects/import_export/project_tree_saver.rb
@@ -0,0 +1,42 @@
+module Projects
+ module ImportExport
+ class ProjectTreeSaver
+ attr_reader :full_path
+
+ def initialize(project: )
+ @project = project
+ end
+
+ def save
+ @full_path = File.join(export_path, project_filename)
+ save_to_disk
+ end
+
+ private
+
+ def save_to_disk
+ FileUtils.mkdir_p(export_path)
+ File.write(full_path, project_json_tree)
+ true
+ rescue
+ #TODO: handle error
+ false
+ end
+
+ def export_path
+ @export_path ||= ImportExport.export_path(@project.name)
+ end
+
+ def project_filename
+ # TODO sanitize name
+ "#{@project.name}.json"
+ end
+
+ def project_json_tree
+ # TODO confirm children, also add subchildren (i.e comments)
+ # TODO confirm atts for children
+ @project.to_json(only: ImportExport.project_atts, include: ImportExport.project_tree)
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb
new file mode 100644
index 00000000000..00e44a9f335
--- /dev/null
+++ b/spec/services/projects/import_export/project_tree_saver_spec.rb
@@ -0,0 +1,83 @@
+require 'spec_helper'
+
+describe Projects::ImportExport::ProjectTreeSaver, services: true do
+ describe :save do
+
+ let(:user) { create(:user) }
+ let!(:project) { create(:project, :public, name: 'searchable_project') }
+ let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" }
+ let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project) }
+
+ before(:each) do
+ project.team << [user, :master]
+ allow_any_instance_of(Projects::ImportExport::ProjectTreeSaver).to receive(:export_path).and_return(export_path)
+ end
+
+ after(:each) do
+ FileUtils.rm_rf(export_path)
+ end
+
+ it 'saves project successfully' do
+ expect(project_tree_saver.save).to be true
+ end
+
+ it 'saves the correct json' do
+ project_tree_saver.save
+ expect(project_json(project_tree_saver.full_path)).to include({ "name" => project.name })
+ end
+ end
+
+ def project_json(filename)
+ JSON.parse(IO.read(filename))
+ end
+
+ # TODO: Remove this. Current JSON pretty printed:
+ # {
+ # "id": 1,
+ # "name": "searchable_project",
+ # "path": "gitlabhq",
+ # "description": null,
+ # "issues_enabled": true,
+ # "wall_enabled": false,
+ # "merge_requests_enabled": true,
+ # "wiki_enabled": true,
+ # "snippets_enabled": true,
+ # "visibility_level": 20,
+ # "archived": false,
+ # "issues": [
+ #
+ # ],
+ # "merge_requests": [
+ #
+ # ],
+ # "labels": [
+ #
+ # ],
+ # "milestones": [
+ #
+ # ],
+ # "snippets": [
+ #
+ # ],
+ # "releases": [
+ #
+ # ],
+ # "events": [
+ # {
+ # "id": 1,
+ # "target_type": null,
+ # "target_id": null,
+ # "title": null,
+ # "data": null,
+ # "project_id": 1,
+ # "created_at": "2016-03-07T17:05:20.926Z",
+ # "updated_at": "2016-03-07T17:05:20.926Z",
+ # "action": 8,
+ # "author_id": 3
+ # }
+ # ],
+ # "commit_statuses": [
+ #
+ # ]
+ # }
+end