diff --git a/config/routes.rb b/config/routes.rb index 236f08c25f3..37a93cd2698 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,7 +9,7 @@ require_dependency "permalink_constraint" # and makes Guard not work properly. USERNAME_ROUTE_FORMAT = /[\w.\-]+/ unless defined? USERNAME_ROUTE_FORMAT -BACKUP_ROUTE_FORMAT = /.+\.(tar\.gz|tgz)/i unless defined? BACKUP_ROUTE_FORMAT +BACKUP_ROUTE_FORMAT = /.+\.(sql\.gz|tar\.gz|tgz)/i unless defined? BACKUP_ROUTE_FORMAT Discourse::Application.routes.draw do diff --git a/lib/backup_restore/backup_restore.rb b/lib/backup_restore/backup_restore.rb index 54c572ece92..af4670fb125 100644 --- a/lib/backup_restore/backup_restore.rb +++ b/lib/backup_restore/backup_restore.rb @@ -6,6 +6,7 @@ module BackupRestore class OperationRunningError < RuntimeError; end + VERSION_PREFIX = "v".freeze DUMP_FILE = "dump.sql" METADATA_FILE = "meta.json" LOGS_CHANNEL = "/admin/backups/logs" diff --git a/lib/backup_restore/backuper.rb b/lib/backup_restore/backuper.rb index d83364392a3..ba890a10b82 100644 --- a/lib/backup_restore/backuper.rb +++ b/lib/backup_restore/backuper.rb @@ -28,8 +28,6 @@ module BackupRestore ensure_directory_exists(@tmp_directory) ensure_directory_exists(@archive_directory) - write_metadata - ### READ-ONLY / START ### enable_readonly_mode @@ -43,7 +41,7 @@ module BackupRestore log "Finalizing backup..." - create_archive + @with_uploads ? create_archive : move_dump_backup after_create_hook rescue SystemExit @@ -54,7 +52,7 @@ module BackupRestore @success = false else @success = true - "#{@archive_basename}.tar.gz" + @backup_filename ensure begin notify_user @@ -84,9 +82,16 @@ module BackupRestore @timestamp = Time.now.strftime("%Y-%m-%d-%H%M%S") @tmp_directory = File.join(Rails.root, "tmp", "backups", @current_db, @timestamp) @dump_filename = "#{File.join(@tmp_directory, BackupRestore::DUMP_FILE)}.gz" - @meta_filename = File.join(@tmp_directory, BackupRestore::METADATA_FILE) @archive_directory = File.join(Rails.root, "public", "backups", @current_db) - @archive_basename = File.join(@archive_directory, "#{SiteSetting.title.parameterize}-#{@timestamp}") + @archive_basename = File.join(@archive_directory, "#{SiteSetting.title.parameterize}-#{@timestamp}-#{BackupRestore::VERSION_PREFIX}#{BackupRestore.current_version}") + + @backup_filename = + if @with_uploads + "#{File.basename(@archive_basename)}.tar.gz" + else + "#{File.basename(@archive_basename)}.sql.gz" + end + @logs = [] @readonly_mode_was_enabled = Discourse.readonly_mode? || !SiteSetting.readonly_mode_during_backup end @@ -137,15 +142,6 @@ module BackupRestore false end - def write_metadata - log "Writing metadata to '#{@meta_filename}'..." - metadata = { - source: "discourse", - version: BackupRestore.current_version - } - File.write(@meta_filename, metadata.to_json) - end - def dump_public_schema log "Dumping the public schema of the database..." @@ -199,8 +195,19 @@ module BackupRestore ].join(" ") end + def move_dump_backup + log "Finalizing database dump file: #{@backup_filename}" + + execute_command( + "mv #{@dump_filename} #{File.join(@archive_directory, @backup_filename)}", + "Failed to move database dump file." + ) + + remove_tmp_directory + end + def create_archive - log "Creating archive: #{File.basename(@archive_basename)}.tar.gz" + log "Creating archive: #{@backup_filename}" tar_filename = "#{@archive_basename}.tar" @@ -219,26 +226,16 @@ module BackupRestore ) end - log "Archiving metadata..." - FileUtils.cd(File.dirname(@meta_filename)) do + upload_directory = "uploads/" + @current_db + + log "Archiving uploads..." + FileUtils.cd(File.join(Rails.root, "public")) do execute_command( - "tar --append --dereference --file #{tar_filename} #{File.basename(@meta_filename)}", - "Failed to archive metadata." + "tar --append --dereference --file #{tar_filename} #{upload_directory}", + "Failed to archive uploads." ) end - if @with_uploads - upload_directory = "uploads/" + @current_db - - log "Archiving uploads..." - FileUtils.cd(File.join(Rails.root, "public")) do - execute_command( - "tar --append --dereference --file #{tar_filename} #{upload_directory}", - "Failed to archive uploads." - ) - end - end - remove_tmp_directory log "Gzipping archive, this may take a while..." @@ -247,7 +244,7 @@ module BackupRestore def after_create_hook log "Executing the after_create_hook for the backup..." - backup = Backup.create_from_filename("#{File.basename(@archive_basename)}.tar.gz") + backup = Backup.create_from_filename(@backup_filename) backup.after_create_hook end diff --git a/lib/backup_restore/restorer.rb b/lib/backup_restore/restorer.rb index b2858bc0c56..837678f2877 100644 --- a/lib/backup_restore/restorer.rb +++ b/lib/backup_restore/restorer.rb @@ -110,13 +110,18 @@ module BackupRestore @archive_filename = File.join(@tmp_directory, @filename) @tar_filename = @archive_filename[0...-3] @meta_filename = File.join(@tmp_directory, BackupRestore::METADATA_FILE) + @is_archive = !(@filename =~ /.sql.gz$/) # For backwards compatibility @dump_filename = - if system("tar --list --file #{@source_filename} #{BackupRestore::DUMP_FILE}") - File.join(@tmp_directory, BackupRestore::DUMP_FILE) + if @is_archive + if system("tar --list --file #{@source_filename} #{BackupRestore::DUMP_FILE}") + File.join(@tmp_directory, BackupRestore::DUMP_FILE) + else + File.join(@tmp_directory, "#{BackupRestore::DUMP_FILE}.gz") + end else - File.join(@tmp_directory, "#{BackupRestore::DUMP_FILE}.gz") + File.join(@tmp_directory, @filename) end @logs = [] @@ -175,7 +180,10 @@ module BackupRestore end def unzip_archive + return unless @is_archive + log "Unzipping archive, this may take a while..." + FileUtils.cd(@tmp_directory) do execute_command("gzip --decompress '#{@archive_filename}'", "Failed to unzip archive.") end @@ -184,14 +192,23 @@ module BackupRestore def extract_metadata log "Extracting metadata file..." - FileUtils.cd(@tmp_directory) do - execute_command( - "tar --extract --file '#{@tar_filename}' #{BackupRestore::METADATA_FILE}", - "Failed to extract metadata file." - ) - end + @metadata = + if system("tar --list --file #{@source_filename} #{BackupRestore::METADATA_FILE}") + FileUtils.cd(@tmp_directory) do + execute_command( + "tar --extract --file '#{@tar_filename}' #{BackupRestore::METADATA_FILE}", + "Failed to extract metadata file." + ) + end - @metadata = Oj.load_file(@meta_filename) + Oj.load_file(@meta_filename) + else + if @filename =~ /-#{BackupRestore::VERSION_PREFIX}(\d{14})/ + { "version" => Regexp.last_match[1].to_i } + else + raise "Migration version is missing from the filename." + end + end end def validate_metadata @@ -204,6 +221,8 @@ module BackupRestore end def extract_dump + return unless @is_archive + log "Extracting dump file..." FileUtils.cd(@tmp_directory) do @@ -334,7 +353,7 @@ module BackupRestore end def extract_uploads - if `tar --list --file '#{@tar_filename}' | grep 'uploads/'`.present? + if system("tar --list --file '#{@tar_filename}' 'uploads'") log "Extracting uploads..." FileUtils.cd(File.join(Rails.root, "public")) do execute_command(