uploads_manager.rb 2.33 KB
Newer Older
1 2
# frozen_string_literal: true

3 4 5 6 7
module Gitlab
  module ImportExport
    class UploadsManager
      include Gitlab::ImportExport::CommandLineUtil

8 9
      UPLOADS_BATCH_SIZE = 100

10
      def initialize(project:, shared:, relative_export_path: 'uploads')
11 12 13 14 15
        @project = project
        @shared = shared
        @relative_export_path = relative_export_path
      end

James Lopez's avatar
James Lopez committed
16
      def save
17
        copy_project_uploads
James Lopez's avatar
James Lopez committed
18 19 20 21 22

        true
      rescue => e
        @shared.error(e)
        false
23 24
      end

James Lopez's avatar
James Lopez committed
25 26 27 28
      def restore
        Dir["#{uploads_export_path}/**/*"].each do |upload|
          next if File.directory?(upload)

James Lopez's avatar
James Lopez committed
29
          add_upload(upload)
James Lopez's avatar
James Lopez committed
30
        end
James Lopez's avatar
James Lopez committed
31 32

        true
James Lopez's avatar
James Lopez committed
33 34 35 36 37
      rescue => e
        @shared.error(e)
        false
      end

38 39
      private

James Lopez's avatar
James Lopez committed
40
      def add_upload(upload)
41 42 43 44 45 46
        secret, identifier = upload.split('/').last(2)

        uploader_context = {
          secret: secret,
          identifier: identifier
        }
James Lopez's avatar
James Lopez committed
47

48
        UploadService.new(@project, File.open(upload, 'r'), FileUploader, uploader_context).execute.to_h
James Lopez's avatar
James Lopez committed
49 50
      end

51
      def copy_project_uploads
52
        each_uploader do |uploader|
James Lopez's avatar
James Lopez committed
53
          next unless uploader.file
54

55 56 57 58 59 60 61
          if uploader.upload.local?
            next unless uploader.upload.exist?

            copy_files(uploader.absolute_path, File.join(uploads_export_path, uploader.upload.path))
          else
            download_and_copy(uploader)
          end
62 63 64 65 66 67 68
        end
      end

      def uploads_export_path
        @uploads_export_path ||= File.join(@shared.export_path, @relative_export_path)
      end

69
      def each_uploader
70 71 72 73 74
        avatar_path = @project.avatar&.upload&.path

        if @relative_export_path == 'avatar'
          yield(@project.avatar)
        else
75
          project_uploads_except_avatar(avatar_path).find_each(batch_size: UPLOADS_BATCH_SIZE) do |upload|
76
            yield(upload.build_uploader)
77 78 79 80
          end
        end
      end

81
      def project_uploads_except_avatar(avatar_path)
82 83 84 85 86
        return @project.uploads unless avatar_path

        @project.uploads.where("path != ?", avatar_path)
      end

87
      def download_and_copy(upload)
James Lopez's avatar
James Lopez committed
88 89
        secret = upload.try(:secret) || ''
        upload_path = File.join(uploads_export_path, secret, upload.filename)
90

James Lopez's avatar
James Lopez committed
91
        mkdir_p(File.join(uploads_export_path, secret))
92

93
        download_or_copy_upload(upload, upload_path)
94 95 96 97
      end
    end
  end
end