summaryrefslogtreecommitdiff
path: root/lib/gitlab/import_export
diff options
context:
space:
mode:
authorJames Lopez <james@jameslopez.es>2016-04-14 16:57:25 +0200
committerJames Lopez <james@jameslopez.es>2016-04-14 16:57:25 +0200
commit0852f539aa389c66ef377b7d567c931f928e147f (patch)
tree82797f5e855f9235d445c943af7161b4cc7d2238 /lib/gitlab/import_export
parent91ffd8028977984d3ea9a741a3a655ff6dae76b2 (diff)
downloadgitlab-ce-0852f539aa389c66ef377b7d567c931f928e147f.tar.gz
refactored stuff, added a save and compress all class and moved mostly everything to lib
Diffstat (limited to 'lib/gitlab/import_export')
-rw-r--r--lib/gitlab/import_export/command_line_util.rb25
-rw-r--r--lib/gitlab/import_export/import_export.yml37
-rw-r--r--lib/gitlab/import_export/import_export_reader.rb91
-rw-r--r--lib/gitlab/import_export/project_tree_saver.rb36
-rw-r--r--lib/gitlab/import_export/repo_bundler.rb38
-rw-r--r--lib/gitlab/import_export/saver.rb38
-rw-r--r--lib/gitlab/import_export/shared.rb13
-rw-r--r--lib/gitlab/import_export/wiki_repo_bundler.rb34
8 files changed, 312 insertions, 0 deletions
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
new file mode 100644
index 00000000000..7bf4b476b6c
--- /dev/null
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -0,0 +1,25 @@
+module Gitlab
+ module ImportExport
+ module CommandLineUtil
+ def tar_cf(archive:, dir:)
+ tar_with_options(archive: archive, dir: dir, options: 'cf')
+ end
+
+ def tar_czf(archive:, dir:)
+ tar_with_options(archive: archive, dir: dir, options: 'czf')
+ end
+
+ def git_bundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:)
+ cmd = %W(#{git_bin_path} --git-dir=#{repo_path} bundle create #{bundle_path} --all)
+ _output, status = Gitlab::Popen.popen(cmd)
+ status.zero?
+ end
+
+ def tar_with_options(archive:, dir:, options:)
+ cmd = %W(tar -#{options} #{archive} -C #{dir} .)
+ _output, status = Gitlab::Popen.popen(cmd)
+ status.zero?
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
new file mode 100644
index 00000000000..92f492e9013
--- /dev/null
+++ b/lib/gitlab/import_export/import_export.yml
@@ -0,0 +1,37 @@
+# Class relationships to be included in the project import/export
+:project_tree:
+ - :issues:
+ - :notes
+ - :labels
+ - :milestones
+ - :snippets
+ - :releases
+ - :events
+ - :project_members:
+ - :user
+ - :merge_requests:
+ - :merge_request_diff
+ - :notes
+ - :ci_commits:
+ - :statuses
+
+:attributes_only:
+ :project:
+ - :name
+ - :path
+ - :description
+ - :issues_enabled
+ - :wall_enabled
+ - :merge_requests_enabled
+ - :wiki_enabled
+ - :snippets_enabled
+ - :visibility_level
+ - :archived
+ :user:
+ - :id
+ - :email
+ - :username
+
+:attributes_except:
+ :snippets:
+ - :expired_at \ No newline at end of file
diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb
new file mode 100644
index 00000000000..717d3026f9e
--- /dev/null
+++ b/lib/gitlab/import_export/import_export_reader.rb
@@ -0,0 +1,91 @@
+module Gitlab
+ module ImportExport
+ module ImportExportReader
+ extend self
+
+ def project_tree
+ { only: atts_only[:project], include: build_hash(tree) }
+ end
+
+ def tree
+ config[:project_tree]
+ end
+
+ private
+
+ def config
+ @config ||= YAML.load_file('lib/gitlab/import_export/import_export.yml')
+ end
+
+ def atts_only
+ config[:attributes_only]
+ end
+
+ def atts_except
+ config[:attributes_except]
+ end
+
+ def build_hash(array)
+ array.map do |el|
+ if el.is_a?(Hash)
+ process_include(el)
+ else
+ only_except_hash = check_only_and_except(el)
+ only_except_hash.empty? ? el : { el => only_except_hash }
+ end
+ end
+ end
+
+ def process_include(hash, included_classes_hash = {})
+ hash.values.flatten.each do |value|
+ current_key = hash.keys.first
+ value = process_current_class(hash, included_classes_hash, value)
+ if included_classes_hash[current_key]
+ add_class(current_key, included_classes_hash, value)
+ else
+ add_new_class(current_key, included_classes_hash, value)
+ end
+ end
+ included_classes_hash
+ end
+
+ def process_current_class(hash, included_classes_hash, value)
+ value = value.is_a?(Hash) ? process_include(hash, included_classes_hash) : value
+ only_except_hash = check_only_and_except(hash.keys.first)
+ included_classes_hash[hash.keys.first] ||= only_except_hash unless only_except_hash.empty?
+ value
+ end
+
+ def add_new_class(current_key, included_classes_hash, value)
+ new_hash = { include: value }
+ new_hash.merge!(check_only_and_except(value))
+ included_classes_hash[current_key] = new_hash
+ end
+
+ def add_class(current_key, included_classes_hash, value)
+ only_except_hash = check_only_and_except(value)
+ value = { value => only_except_hash } unless only_except_hash.empty?
+ old_values = included_classes_hash[current_key][:include]
+ included_classes_hash[current_key][:include] = ([old_values] + [value]).compact.flatten
+ end
+
+ def check_only_and_except(value)
+ check_only(value).merge(check_except(value))
+ end
+
+ def check_only(value)
+ key = key_from_hash(value)
+ atts_only[key].nil? ? {} : { only: atts_only[key] }
+ end
+
+ def check_except(value)
+ key = key_from_hash(value)
+ atts_except[key].nil? ? {} : { except: atts_except[key] }
+ end
+
+ def key_from_hash(value)
+ value.is_a?(Hash) ? value.keys.first : value
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb
new file mode 100644
index 00000000000..b2615f8273b
--- /dev/null
+++ b/lib/gitlab/import_export/project_tree_saver.rb
@@ -0,0 +1,36 @@
+module Gitlab
+ module ImportExport
+ class ProjectTreeSaver
+ attr_reader :full_path
+
+ def initialize(project: , shared: )
+ @project = project
+ @export_path = shared.export_path
+ 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 project_filename
+ "#{@project.name}.json"
+ end
+
+ def project_json_tree
+ @project.to_json(Gitlab::ImportExport.project_tree)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb
new file mode 100644
index 00000000000..7a1c2a12a53
--- /dev/null
+++ b/lib/gitlab/import_export/repo_bundler.rb
@@ -0,0 +1,38 @@
+module Gitlab
+ module ImportExport
+ class RepoBundler
+ include Gitlab::ImportExport::CommandLineUtil
+
+ attr_reader :full_path
+
+ def initialize(project: , shared: )
+ @project = project
+ @export_path = shared.export_path
+ end
+
+ def bundle
+ return false if @project.empty_repo?
+ @full_path = File.join(@export_path, project_filename)
+ bundle_to_disk
+ end
+
+ private
+
+ def bundle_to_disk
+ FileUtils.mkdir_p(@export_path)
+ tar_cf(archive: full_path, dir: path_to_repo)
+ rescue
+ #TODO: handle error
+ false
+ end
+
+ def project_filename
+ "#{@project.name}.bundle"
+ end
+
+ def path_to_repo
+ @project.repository.path_to_repo
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
new file mode 100644
index 00000000000..f26804d2402
--- /dev/null
+++ b/lib/gitlab/import_export/saver.rb
@@ -0,0 +1,38 @@
+module Gitlab
+ module ImportExport
+ class Saver
+ include Gitlab::ImportExport::CommandLineUtil
+
+ def self.save(*args)
+ new(*args).save
+ end
+
+ def initialize(storage_path:)
+ @storage_path = storage_path
+ end
+
+ def save
+ if compress_and_save
+ remove_storage_path
+ archive_file
+ else
+ false
+ end
+ end
+
+ private
+
+ def compress_and_save
+ tar_czf(archive: archive_file, dir: @storage_path)
+ end
+
+ def remove_storage_path
+ FileUtils.rm_rf(@storage_path)
+ end
+
+ def archive_file
+ @archive_file ||= File.join(@storage_path, '..', 'project.tar.gz')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb
new file mode 100644
index 00000000000..a4ec33a6cf7
--- /dev/null
+++ b/lib/gitlab/import_export/shared.rb
@@ -0,0 +1,13 @@
+module Gitlab
+ module ImportExport
+ class Shared
+ def initialize(opts)
+ @opts = opts
+ end
+
+ def export_path
+ @export_path ||= Gitlab::ImportExport.export_path(relative_path: @opts[:relative_path])
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/wiki_repo_bundler.rb b/lib/gitlab/import_export/wiki_repo_bundler.rb
new file mode 100644
index 00000000000..9ef0febee54
--- /dev/null
+++ b/lib/gitlab/import_export/wiki_repo_bundler.rb
@@ -0,0 +1,34 @@
+module Gitlab
+ module ImportExport
+ class WikiRepoBundler < RepoBundler
+ def bundle
+ @wiki = ProjectWiki.new(@project)
+ return false if !wiki?
+ @full_path = File.join(@export_path, project_filename)
+ bundle_to_disk
+ end
+
+ def bundle_to_disk
+ FileUtils.mkdir_p(@export_path)
+ git_bundle(repo_path: path_to_repo, bundle_path: @full_path)
+ rescue
+ #TODO: handle error
+ false
+ end
+
+ private
+
+ def project_filename
+ "#{@project.name}.wiki.bundle"
+ end
+
+ def path_to_repo
+ @wiki.repository.path_to_repo
+ end
+
+ def wiki?
+ File.exists?(@wiki.repository.path_to_repo) && !@wiki.repository.empty?
+ end
+ end
+ end
+end