discourse/lib/backup_restore/meta_data_handler.rb
2023-01-09 12:10:19 +00:00

67 lines
1.9 KiB
Ruby

# frozen_string_literal: true
module BackupRestore
MetaDataError = Class.new(RuntimeError)
MigrationRequiredError = Class.new(RuntimeError)
class MetaDataHandler
METADATA_FILE = "meta.json"
delegate :log, to: :@logger, private: true
def initialize(logger, filename, tmp_directory)
@logger = logger
@current_version = BackupRestore.current_version
@filename = filename
@tmp_directory = tmp_directory
end
def validate
metadata = extract_metadata
if !metadata[:version].is_a?(Integer)
raise MetaDataError.new("Version is not in a valid format.")
end
log "Validating metadata..."
log " Current version: #{@current_version}"
log " Restored version: #{metadata[:version]}"
if metadata[:version] > @current_version
raise MigrationRequiredError.new(
"You're trying to restore a more recent version of the schema. " \
"You should migrate first!",
)
end
metadata
end
protected
# Tries to extract the backup version from an existing
# metadata file (used in Discourse < v1.6) or from the filename.
def extract_metadata
metadata_path = File.join(@tmp_directory, METADATA_FILE) if @tmp_directory.present?
if metadata_path.present? && File.exist?(metadata_path)
metadata = load_metadata_file(metadata_path)
elsif @filename =~ /-#{BackupRestore::VERSION_PREFIX}(\d{14})/
metadata = { version: Regexp.last_match[1].to_i }
else
raise MetaDataError.new("Migration version is missing from the filename.")
end
metadata
end
def load_metadata_file(path)
metadata = JSON.parse(File.read(path), symbolize_names: true)
raise MetaDataError.new("Failed to load metadata file.") if metadata.blank?
metadata
rescue JSON::ParserError
raise MetaDataError.new("Failed to parse metadata file.")
end
end
end