summaryrefslogtreecommitdiff
path: root/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
blob: d39b6fe59559bd15477d88374c9b3270b76fec47 (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
# 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)

        AFTER_EXPORT_LOCK_FILE_NAME = '.after_export_action'.freeze

        private

        attr_reader :project, :current_user

        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

          return unless @project.export_status == :finished

          @current_user = current_user

          if invalid?
            log_validation_errors

            return
          end

          create_or_update_after_export_lock
          strategy_execute

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

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

        def self.lock_file_path(project)
          return unless project.export_path || export_file_exists?

          lock_path = project.import_export_shared.archive_path

          mkdir_p(lock_path)
          File.join(lock_path, AFTER_EXPORT_LOCK_FILE_NAME)
        end

        protected

        def strategy_execute
          raise NotImplementedError
        end

        private

        def create_or_update_after_export_lock
          FileUtils.touch(self.class.lock_file_path(project))
        end

        def delete_after_export_lock
          lock_file = self.class.lock_file_path(project)

          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

        def export_file_exists?
          project.export_file_exists?
        end
      end
    end
  end
end