summaryrefslogtreecommitdiff
path: root/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
blob: b43d0a0c3eb79f1d824c7d19a36bd39ec9b59db8 (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# frozen_string_literal: true

module Gitlab
  module ImportExport
    module AfterExportStrategies
      class BaseAfterExportStrategy
        extend Gitlab::ImportExport::CommandLineUtil
        include ActiveModel::Validations
        extend Forwardable

        StrategyError = Class.new(StandardError)

        private

        attr_reader :project, :current_user, :lock_file

        public

        def initialize(attributes = {})
          @options = OpenStruct.new(attributes)

          self.class.instance_eval do
            def_delegators :@options, *attributes.keys
          end
        end

        def execute(current_user, project)
          @project = project

          ensure_export_ready!
          ensure_lock_files_path!
          @lock_file = File.join(lock_files_path, SecureRandom.hex)
          @current_user = current_user

          if invalid?
            log_validation_errors

            return
          end

          create_or_update_after_export_lock
          strategy_execute

          true
        rescue StandardError => e
          project.import_export_shared.error(e)
          false
        ensure
          delete_after_export_lock
          delete_export_file
          delete_archive_path
        end

        def to_json(options = {})
          @options.to_h.merge!(klass: self.class.name).to_json
        end

        def ensure_export_ready!
          raise StrategyError unless project.export_file_exists?
        end

        def ensure_lock_files_path!
          FileUtils.mkdir_p(lock_files_path) unless Dir.exist?(lock_files_path)
        end

        def lock_files_path
          project.import_export_shared.lock_files_path
        end

        def archive_path
          project.import_export_shared.archive_path
        end

        def locks_present?
          project.import_export_shared.locks_present?
        end

        protected

        def strategy_execute
          raise NotImplementedError
        end

        def delete_export?
          true
        end

        private

        def delete_export_file
          return if locks_present? || !delete_export?

          project.remove_exports
        end

        def delete_archive_path
          FileUtils.rm_rf(archive_path) if File.directory?(archive_path)
        end

        def create_or_update_after_export_lock
          FileUtils.touch(lock_file)
        end

        def delete_after_export_lock
          FileUtils.rm(lock_file) if lock_file.present? && File.exist?(lock_file)
        end

        def log_validation_errors
          errors.full_messages.each { |msg| project.import_export_shared.add_error_message(msg) }
        end
      end
    end
  end
end