local helpers = require('helpers')
local recovery = require('recovery')
local paths = require('paths')
local consts = require('consts')
local ltar = require('ltar')
local lfs = require('lfs')
local json = require('lunajson')
local migration = require('migration')
local restore = {}
local unpacked_backup_dir = paths.temp_dir .. "/backup"
restore.script_name = "restore.lua"
restore.img_in_progress = "assets/gui_image_restore_in_progress.bin"
restore.img_success = "assets/gui_image_restore_success.bin"
restore.img_failure = "assets/gui_image_restore_failed.bin"
local function check_available_space()
local backup_size = lfs.attributes(paths.backup_file, 'size')
local available_space = recovery.sys.free_space(recovery.sys.user())
print(string.format("Checking disk space:\nNeeded space: %d bytes, available space: %d bytes", backup_size,
available_space))
assert(available_space > backup_size, "Not enough free space on user disk")
end
local function unpack_backup()
if helpers.exists(unpacked_backup_dir) then
print(string.format("Directory '%s' exists, removing", unpacked_backup_dir))
helpers.rmdir(unpacked_backup_dir)
end
lfs.mkdir(unpacked_backup_dir)
print(string.format("Unpacking backup file '%s' to '%s'", paths.backup_file, unpacked_backup_dir))
ltar.unpack(paths.backup_file, unpacked_backup_dir)
end
local function get_db_array_from_file(file)
local contents = helpers.read_whole_file(file)
local root = json.decode(contents)
local set = {}
for _, entry in pairs(root.databases) do
set[entry.name] = tonumber(entry.version)
end
return set
end
local function get_db_array_from_path(path)
local set = {}
for file in lfs.dir(path) do
local file_path = path .. "/" .. file
if file ~= "." and file ~= ".." then
if lfs.attributes(file_path, "mode") == "file" then
set[helpers.strip_from_extension(file)] = true;
end
end
end
return set
end
local function build_db_set()
local system_db_set = get_db_array_from_file(paths.version_file)
local backup_db_set = get_db_array_from_path(unpacked_backup_dir)
local set = {}
for name, version in pairs(system_db_set) do
if backup_db_set[name] then
set[name] = tonumber(version)
end
end
return set
end
local function perform_db_migration()
print("Performing database migration")
local result = migration.migrate(unpacked_backup_dir, paths.migration_scripts_dir, build_db_set())
assert(result == migration.retcode.OK, string.format("Database migration process failed with %d", result))
end
local function sync_databases()
print("Syncing databases:")
for name, _ in pairs(build_db_set()) do
local destination = paths.db_dir .. "/" .. name .. ".db"
local source = unpacked_backup_dir .. "/" .. name .. ".db"
print(string.format("Replacing '%s' with '%s'", destination, source));
assert(os.remove(destination))
helpers.copy_file(source, destination)
end
end
local function remove_cache()
if helpers.exists(paths.file_indexer_cache) then
print(string.format("Removing cache file '%s'", paths.file_indexer_cache))
assert(os.remove(paths.file_indexer_cache))
end
end
local function cleanup()
if helpers.exists(unpacked_backup_dir) then
helpers.rmdir(unpacked_backup_dir)
end
end
function restore.execute()
check_available_space()
unpack_backup()
perform_db_migration()
sync_databases()
remove_cache()
cleanup()
end
return restore