blob: 5a6f6e017d2f5cdd6ac3ca285441d4df7f828ea3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
# frozen_string_literal: true
module Gitlab
module ImportExport
class FileImporter
include Gitlab::ImportExport::CommandLineUtil
ImporterError = Class.new(StandardError)
MAX_RETRIES = 8
IGNORED_FILENAMES = %w(. ..).freeze
def self.import(*args, **kwargs)
new(*args, **kwargs).import
end
def initialize(importable:, archive_file:, shared:)
@importable = importable
@archive_file = archive_file
@shared = shared
end
def import
mkdir_p(@shared.export_path)
mkdir_p(@shared.archive_path)
remove_symlinks
copy_archive
wait_for_archived_file do
# Disable archive validation by default
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/235949
validate_decompressed_archive_size if Feature.enabled?(:validate_import_decompressed_archive_size)
decompress_archive
end
rescue => e
@shared.error(e)
false
ensure
remove_import_file
remove_symlinks
end
private
# Exponentially sleep until I/O finishes copying the file
def wait_for_archived_file
MAX_RETRIES.times do |retry_number|
break if File.exist?(@archive_file)
sleep(2**retry_number)
end
yield
end
def decompress_archive
result = untar_zxf(archive: @archive_file, dir: @shared.export_path)
raise ImporterError.new("Unable to decompress #{@archive_file} into #{@shared.export_path}") unless result
result
end
def copy_archive
return if @archive_file
@archive_file = File.join(@shared.archive_path, Gitlab::ImportExport.export_filename(exportable: @importable))
download_or_copy_upload(@importable.import_export_upload.import_file, @archive_file)
end
def remove_symlinks
extracted_files.each do |path|
FileUtils.rm(path) if File.lstat(path).symlink?
end
true
end
def remove_import_file
FileUtils.rm_rf(@archive_file)
end
def extracted_files
Dir.glob("#{@shared.export_path}/**/*", File::FNM_DOTMATCH).reject { |f| IGNORED_FILENAMES.include?(File.basename(f)) }
end
def validate_decompressed_archive_size
raise ImporterError.new(size_validator.error) unless size_validator.valid?
end
def size_validator
@size_validator ||= DecompressedArchiveSizeValidator.new(archive_path: @archive_file)
end
end
end
end
|