138 lines
4.1 KiB
Lua
138 lines
4.1 KiB
Lua
--- Mod migration and version comparison functions.
|
|
--- ```lua
|
|
--- local flib_migration = require("__flib__/migration")
|
|
--- ```
|
|
--- @class flib_migration
|
|
local flib_migration = {}
|
|
|
|
local string = string
|
|
local table = table
|
|
|
|
local version_pattern = "%d+"
|
|
local version_format = "%02d"
|
|
|
|
--- Normalize version strings for easy comparison.
|
|
---
|
|
--- ### Examples
|
|
---
|
|
--- ```lua
|
|
--- migration.format_version("1.10.1234", "%04d")
|
|
--- migration.format_version("3", "%02d")
|
|
--- ```
|
|
--- @param version string
|
|
--- @param format string? default: `%02d`
|
|
--- @return string?
|
|
function flib_migration.format_version(version, format)
|
|
if version then
|
|
format = format or version_format
|
|
local tbl = {}
|
|
for v in string.gmatch(version, version_pattern) do
|
|
tbl[#tbl + 1] = string.format(format, v)
|
|
end
|
|
if next(tbl) then
|
|
return table.concat(tbl, ".")
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--- Check if current_version is newer than old_version.
|
|
--- @param old_version string
|
|
--- @param current_version string
|
|
--- @param format string? default: `%02d`
|
|
--- @return boolean?
|
|
function flib_migration.is_newer_version(old_version, current_version, format)
|
|
local v1 = flib_migration.format_version(old_version, format)
|
|
local v2 = flib_migration.format_version(current_version, format)
|
|
if v1 and v2 then
|
|
if v2 > v1 then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--- Run migrations against the given version.
|
|
--- @param old_version string
|
|
--- @param migrations MigrationsTable
|
|
--- @param format? string default: `%02d`
|
|
--- @param ... any All additional arguments will be passed to each function within `migrations`.
|
|
function flib_migration.run(old_version, migrations, format, ...)
|
|
local migrate = false
|
|
for version, func in pairs(migrations) do
|
|
if migrate or flib_migration.is_newer_version(old_version, version, format) then
|
|
migrate = true
|
|
func(...)
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Determine if migrations need to be run for this mod, then run them if needed.
|
|
---
|
|
--- ### Examples
|
|
---
|
|
--- ```lua
|
|
--- script.on_configuration_changed(function(e)
|
|
--- if migration.on_config_changed(e, migrations) then
|
|
--- -- Run generic (non-init) migrations
|
|
--- rebuild_prototype_data()
|
|
--- end
|
|
--- end
|
|
--- ```
|
|
--- @param e ConfigurationChangedData
|
|
--- @param migrations? MigrationsTable
|
|
--- @param mod_name? string The mod to check against. Defaults to the current mod.
|
|
--- @param ... any All additional arguments will be passed to each function within `migrations`.
|
|
--- @return boolean run_generic_micrations
|
|
function flib_migration.on_config_changed(e, migrations, mod_name, ...)
|
|
local changes = e.mod_changes[mod_name or script.mod_name]
|
|
local old_version = changes and changes.old_version
|
|
if old_version or not changes then
|
|
if migrations then
|
|
flib_migration.run(old_version, migrations, nil, ...)
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Handle on_configuration_changed with the given generic and version-specific migrations. Will override any existing
|
|
--- on_configuration_changed event handler. Both arguments are optional.
|
|
--- @param version_migrations MigrationsTable?
|
|
--- @param generic_handler fun(e: ConfigurationChangedData)?
|
|
function flib_migration.handle_on_configuration_changed(version_migrations, generic_handler)
|
|
script.on_configuration_changed(function(e)
|
|
if flib_migration.on_config_changed(e, version_migrations) and generic_handler then
|
|
generic_handler(e)
|
|
end
|
|
end)
|
|
end
|
|
|
|
return flib_migration
|
|
|
|
--- Migration code to run for specific mod version. A given function will run if the previous mod version is less
|
|
--- than the given version.
|
|
---
|
|
--- # Example
|
|
---
|
|
--- ```lua
|
|
--- {
|
|
--- ["1.0.1"] = function()
|
|
--- global.foo = nil
|
|
--- for _, player_table in pairs(global.players) do
|
|
--- player_table.bar = "Lorem ipsum"
|
|
--- end
|
|
--- end,
|
|
--- ["1.0.7"] = function()
|
|
--- global.bar = {}
|
|
--- end
|
|
--- ["1.1.0"] = function(arg)
|
|
--- global.foo = arg
|
|
--- end
|
|
--- }
|
|
--- ```
|
|
---
|
|
--- If the mod is upgraded from 1.0.4 to 1.1.0, then the migrations for 1.0.7 and 1.1.0 will be run.
|
|
--- @alias MigrationsTable table<string, fun(...: any)>
|