gitlab_uploader.rb 2.68 KB
Newer Older
1 2
# frozen_string_literal: true

3
class GitlabUploader < CarrierWave::Uploader::Base
4
  class_attribute :options
5

6 7 8 9 10
  class << self
    # DSL setter
    def storage_options(options)
      self.options = options
    end
11

12 13 14
    def root
      options.storage_path
    end
15

16 17 18 19
    # represent the directory namespacing at the class level
    def base_dir
      options.fetch('base_dir', '')
    end
20

21 22 23 24 25 26 27
    def file_storage?
      storage == CarrierWave::Storage::File
    end

    def absolute_path(upload_record)
      File.join(root, upload_record.path)
    end
28 29
  end

30 31
  storage_options Gitlab.config.uploads

32 33
  delegate :base_dir, :file_storage?, to: :class

34 35 36 37
  def initialize(model, mounted_as = nil, **uploader_context)
    super(model, mounted_as)
  end

Kamil Trzcinski's avatar
Kamil Trzcinski committed
38
  def file_cache_storage?
39
    cache_storage.is_a?(CarrierWave::Storage::File)
40 41
  end

42
  def move_to_cache
43
    file_storage?
44 45 46
  end

  def move_to_store
47
    file_storage?
48
  end
49 50

  def exists?
51
    file.present?
52
  end
53

54 55 56 57
  def cache_dir
    File.join(root, base_dir, 'tmp/cache')
  end

58
  def work_dir
59
    File.join(root, base_dir, 'tmp/work')
60 61
  end

62 63 64 65
  def filename
    super || file&.filename
  end

66 67 68 69 70 71
  def relative_path
    return path if pathname.relative?

    pathname.relative_path_from(Pathname.new(root))
  end

72 73 74 75
  def model_valid?
    !!model
  end

76 77 78 79
  def local_url
    File.join('/', self.class.base_dir, dynamic_segment, filename)
  end

80 81 82 83
  def cached_size
    size
  end

84
  def open
Kamil Trzciński's avatar
Kamil Trzciński committed
85 86 87 88 89 90
    stream =
      if file_storage?
        File.open(path, "rb") if path
      else
        ::Gitlab::HttpIO.new(url, cached_size) if url
      end
91 92 93 94 95 96 97 98 99 100 101

    return unless stream
    return stream unless block_given?

    begin
      yield(stream)
    ensure
      stream.close
    end
  end

102 103
  private

104 105 106 107 108 109 110 111 112 113 114
  # Designed to be overridden by child uploaders that have a dynamic path
  # segment -- that is, a path that changes based on mutable attributes of its
  # associated model
  #
  # For example, `FileUploader` builds the storage path based on the associated
  # project model's `path_with_namespace` value, which can change when the
  # project or its containing namespace is moved or renamed.
  def dynamic_segment
    raise(NotImplementedError)
  end

115 116 117 118 119 120 121
  # To prevent files from moving across filesystems, override the default
  # implementation:
  # http://github.com/carrierwaveuploader/carrierwave/blob/v1.0.0/lib/carrierwave/uploader/cache.rb#L181-L183
  def workfile_path(for_file = original_filename)
    # To be safe, keep this directory outside of the the cache directory
    # because calling CarrierWave.clean_cache_files! will remove any files in
    # the cache directory.
122
    File.join(work_dir, cache_id, version_name.to_s, for_file)
123
  end
124 125 126 127

  def pathname
    @pathname ||= Pathname.new(path)
  end
128
end