# frozen_string_literal: true module Uploads class Local < Base def keys(relation) relation.includes(:model).find_each.map(&:absolute_path) end def delete_keys(keys) keys.each do |path| delete_file(path) end end private def delete_file(path) unless exists?(path) logger.warn("File '#{path}' doesn't exist, skipping") return end unless in_uploads?(path) message = "Path '#{path}' is not in uploads dir, skipping" logger.warn(message) Gitlab::ErrorTracking.track_and_raise_for_dev_exception( RuntimeError.new(message), uploads_dir: storage_dir) return end FileUtils.rm(path) delete_dir!(File.dirname(path)) end def exists?(path) path.present? && File.exist?(path) end def in_uploads?(path) path.start_with?(storage_dir) end def delete_dir!(path) Dir.rmdir(path) rescue Errno::ENOENT # Ignore: path does not exist rescue Errno::ENOTDIR # Ignore: path is not a dir rescue Errno::ENOTEMPTY, Errno::EEXIST # Ignore: dir is not empty end def storage_dir @storage_dir ||= File.realpath(Gitlab.config.uploads.storage_path) end end end Uploads::Local.prepend_mod