# frozen_string_literal: true # StorageManager is an abstract superclass that defines a simple interface for # storing files on local or remote backends. All image files stored by Danbooru # are handled by a StorageManager. # # A StorageManager has methods for saving, deleting, and opening files, and for # generating URLs for files. # # @abstract # @see StorageManager::Local # @see StorageManager::Mirror # @see StorageManager::Rclone class StorageManager class Error < StandardError; end attr_reader :base_url # Initialize a storage manager object. # # @param base_url [String, nil] the base URL where files are served from (ex: # "https://cdn.donmai.us"), or nil if the files don't have an URL (they're # stored in a publicly inaccessible location). def initialize(base_url: nil) @base_url = base_url end # Store the given file at the given path. If a file already exists at that # location it should be overwritten atomically. Either the file is fully # written, or an error is raised and the original file is left unchanged. The # file should never be in a partially written state. # # @param src_file [File] the file to store # @param path [String] the remote path where the file should be stored def store(io, path) raise NotImplementedError, "store not implemented" end # Delete the file at the given path. If the file doesn't exist, no error # should be raised. # @param path [String] the remote path of the file to be deleted def delete(path) raise NotImplementedError, "delete not implemented" end # Return a readonly copy of the file located at the given path. # @param path [String] the remote path of the file to open # @return [File] the file def open(path) raise NotImplementedError, "open not implemented" end # Copy the file from src_path to dest_path. # # @param src_path [String] The file to copy. # @param dest_path [String] The location to copy the file to. def copy(src_path, dest_path) file = open(src_path) store(file, dest_path) file&.close nil end # Move the file from src_path to dest_path. # # @param src_path [String] The file to move. # @param dest_path [String] The location to move the file to. def move(src_path, dest_path) copy(src_path, dest_path) delete(src_path) nil end # Return the full URL of the file at the given path, or nil if the file # doesn't have an URL. # @return [String, nil] the file URL def file_url(path) return nil if base_dir.nil? File.join(base_url, path) end end