diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-15 12:09:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-15 12:09:33 +0300 |
commit | 25fdad39f53eb46b346076fd07bc2db9bc1d8ccb (patch) | |
tree | b2aec078df9f1414ff11e0940558fa2d8377000a /lib/gitlab/import_export | |
parent | fbea3a224e10049658a7c31bbe7455dc43a4456e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/gitlab/import_export')
-rw-r--r-- | lib/gitlab/import_export/project/exported_relations_merger.rb | 56 | ||||
-rw-r--r-- | lib/gitlab/import_export/project/relation_saver.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/import_export/recursive_merge_folders.rb | 74 |
3 files changed, 131 insertions, 1 deletions
diff --git a/lib/gitlab/import_export/project/exported_relations_merger.rb b/lib/gitlab/import_export/project/exported_relations_merger.rb new file mode 100644 index 00000000000..dda3d00d608 --- /dev/null +++ b/lib/gitlab/import_export/project/exported_relations_merger.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Gitlab + module ImportExport + module Project + class ExportedRelationsMerger + include Gitlab::ImportExport::CommandLineUtil + + def initialize(export_job:, shared:) + @export_job = export_job + @shared = shared + end + + def save + Dir.mktmpdir do |dirpath| + export_job.relation_exports.each do |relation_export| + relation = relation_export.relation + upload = relation_export.upload + filename = upload.export_file.filename + + tar_gz_full_path = File.join(dirpath, filename) + decompress_path = File.join(dirpath, relation) + Gitlab::Utils.check_path_traversal!(tar_gz_full_path) + Gitlab::Utils.check_path_traversal!(decompress_path) + + # Download tar.gz + download_or_copy_upload( + upload.export_file, tar_gz_full_path, size_limit: relation_export.upload.export_file.size + ) + + # Decompress tar.gz + mkdir_p(decompress_path) + untar_zxf(dir: decompress_path, archive: tar_gz_full_path) + File.delete(tar_gz_full_path) + + # Merge decompressed files into export_path + RecursiveMergeFolders.merge(decompress_path, shared.export_path) + FileUtils.rm_r(decompress_path) + rescue StandardError => e + shared.error(e) + false + end + end + + shared.errors.empty? + end + + private + + attr_reader :shared, :export_job + + delegate :project, to: :export_job + end + end + end +end diff --git a/lib/gitlab/import_export/project/relation_saver.rb b/lib/gitlab/import_export/project/relation_saver.rb index 8e91adac196..967239e17c1 100644 --- a/lib/gitlab/import_export/project/relation_saver.rb +++ b/lib/gitlab/import_export/project/relation_saver.rb @@ -32,7 +32,7 @@ module Gitlab project, reader.project_tree, json_writer, - exportable_path: 'project', + exportable_path: 'tree/project', current_user: nil ) end diff --git a/lib/gitlab/import_export/recursive_merge_folders.rb b/lib/gitlab/import_export/recursive_merge_folders.rb new file mode 100644 index 00000000000..982358699bd --- /dev/null +++ b/lib/gitlab/import_export/recursive_merge_folders.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true +# +# This class is used by Import/Export to move files and folders from a source folders into a target folders +# that can already have the same folders in it, resolving in a merged folder. +# +# Example: +# +# source path +# |-- tree +# | |-- project +# | |-- labels.ndjson +# |-- uploads +# | |-- folder1 +# | | |-- image1.png +# | |-- folder2 +# | | |-- image2.png +# +# target path +# |-- tree +# | |-- project +# | |-- issues.ndjson +# |-- uploads +# | |-- folder1 +# | | |-- image3.png +# | |-- folder3 +# | | |-- image4.png +# +# target path after merge +# |-- tree +# | |-- project +# | | |-- issues.ndjson +# | | |-- labels.ndjson +# |-- uploads +# | |-- folder1 +# | | |-- image1.png +# | | |-- image3.png +# | |-- folder2 +# | | |-- image2.png +# | |-- folder3 +# | | |-- image4.png + +module Gitlab + module ImportExport + class RecursiveMergeFolders + DEFAULT_DIR_MODE = 0o700 + + def self.merge(source_path, target_path) + Gitlab::Utils.check_path_traversal!(source_path) + Gitlab::Utils.check_path_traversal!(target_path) + Gitlab::Utils.check_allowed_absolute_path!(source_path, [Dir.tmpdir]) + + recursive_merge(source_path, target_path) + end + + def self.recursive_merge(source_path, target_path) + Dir.children(source_path).each do |child| + source_child = File.join(source_path, child) + target_child = File.join(target_path, child) + + next if File.lstat(source_child).symlink? + + if File.directory?(source_child) + FileUtils.mkdir_p(target_child, mode: DEFAULT_DIR_MODE) unless File.exist?(target_child) + recursive_merge(source_child, target_child) + else + FileUtils.mv(source_child, target_child) + end + end + end + + private_class_method :recursive_merge + end + end +end |