feat: Added system to handle version migrations
This commit is contained in:
parent
9ce64ec6e1
commit
43c88a2fab
@ -38,6 +38,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/debugging.cpp
|
||||
source/helpers/default_paths.cpp
|
||||
source/helpers/imgui_hooks.cpp
|
||||
source/helpers/semantic_version.cpp
|
||||
|
||||
source/test/tests.cpp
|
||||
|
||||
|
@ -217,6 +217,7 @@ namespace hex {
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
EVENT_DEF(EventDPIChanged, float, float);
|
||||
EVENT_DEF(EventWindowFocused, bool);
|
||||
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
|
||||
|
||||
/**
|
||||
* @brief Called when the provider is created.
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/semantic_version.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@ -618,7 +619,7 @@ namespace hex {
|
||||
* @brief Gets the current ImHex version
|
||||
* @return ImHex version
|
||||
*/
|
||||
std::string getImHexVersion(bool withBuildType = true);
|
||||
SemanticVersion getImHexVersion();
|
||||
|
||||
/**
|
||||
* @brief Gets the current git commit hash
|
||||
@ -695,6 +696,13 @@ namespace hex {
|
||||
*/
|
||||
void* getLibImHexModuleHandle();
|
||||
|
||||
/**
|
||||
* Adds a new migration routine that will be executed when upgrading from a lower version than specified in migrationVersion
|
||||
* @param migrationVersion Upgrade point version
|
||||
* @param function Function to run
|
||||
*/
|
||||
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
36
lib/libimhex/include/hex/helpers/semantic_version.hpp
Normal file
36
lib/libimhex/include/hex/helpers/semantic_version.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <compare>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class SemanticVersion {
|
||||
public:
|
||||
SemanticVersion() = default;
|
||||
SemanticVersion(std::string version);
|
||||
SemanticVersion(std::string_view version);
|
||||
SemanticVersion(const char *version);
|
||||
|
||||
std::strong_ordering operator<=>(const SemanticVersion &) const;
|
||||
bool operator==(const SemanticVersion &other) const;
|
||||
|
||||
u32 major() const;
|
||||
u32 minor() const;
|
||||
u32 patch() const;
|
||||
bool nightly() const;
|
||||
const std::string& buildType() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
std::string get(bool withBuildType = true) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_parts;
|
||||
std::string m_buildType;
|
||||
};
|
||||
|
||||
}
|
@ -630,7 +630,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
runtime.addDefine("__IMHEX__");
|
||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion());
|
||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion().get());
|
||||
}
|
||||
|
||||
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
||||
|
@ -645,6 +645,14 @@ namespace hex {
|
||||
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
|
||||
}
|
||||
|
||||
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function) {
|
||||
EventImHexUpdated::subscribe([migrationVersion, function](const SemanticVersion &oldVersion, const SemanticVersion &newVersion) {
|
||||
if (oldVersion < migrationVersion && newVersion >= migrationVersion) {
|
||||
function();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const std::map<std::string, std::string>& getInitArguments() {
|
||||
return *impl::s_initArguments;
|
||||
@ -794,16 +802,11 @@ namespace hex {
|
||||
return { { name, version } };
|
||||
}
|
||||
|
||||
std::string getImHexVersion(bool withBuildType) {
|
||||
SemanticVersion getImHexVersion() {
|
||||
#if defined IMHEX_VERSION
|
||||
if (withBuildType) {
|
||||
return IMHEX_VERSION;
|
||||
} else {
|
||||
auto version = std::string(IMHEX_VERSION);
|
||||
return version.substr(0, version.find('-'));
|
||||
}
|
||||
return SemanticVersion(IMHEX_VERSION);
|
||||
#else
|
||||
return "Unknown";
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -837,7 +840,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool isNightlyBuild() {
|
||||
return getImHexVersion(false).ends_with("WIP");
|
||||
return getImHexVersion().nightly();
|
||||
}
|
||||
|
||||
bool updateImHex(UpdateType updateType) {
|
||||
|
@ -129,7 +129,7 @@ namespace hex {
|
||||
|
||||
|
||||
const auto requestedVersion = getCompatibleVersion();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion().get();
|
||||
if (!imhexVersion.starts_with(requestedVersion)) {
|
||||
if (requestedVersion.empty()) {
|
||||
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));
|
||||
|
96
lib/libimhex/source/helpers/semantic_version.cpp
Normal file
96
lib/libimhex/source/helpers/semantic_version.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/semantic_version.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
SemanticVersion::SemanticVersion(const char *version) : SemanticVersion(std::string(version)) {
|
||||
|
||||
}
|
||||
|
||||
SemanticVersion::SemanticVersion(std::string_view version) : SemanticVersion(std::string(version.begin(), version.end())) {
|
||||
|
||||
}
|
||||
|
||||
SemanticVersion::SemanticVersion(std::string version) {
|
||||
if (version.empty())
|
||||
return;
|
||||
|
||||
if (version.starts_with("v"))
|
||||
version = version.substr(1);
|
||||
|
||||
m_parts = wolv::util::splitString(version, ".");
|
||||
|
||||
if (m_parts.size() != 3 && m_parts.size() != 4) {
|
||||
m_parts.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_parts.back().contains("-")) {
|
||||
auto buildTypeParts = wolv::util::splitString(m_parts.back(), "-");
|
||||
if (buildTypeParts.size() != 2) {
|
||||
m_parts.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_parts.back() = buildTypeParts[0];
|
||||
m_buildType = buildTypeParts[1];
|
||||
}
|
||||
}
|
||||
|
||||
u32 SemanticVersion::major() const {
|
||||
return std::stoul(m_parts[0]);
|
||||
}
|
||||
|
||||
u32 SemanticVersion::minor() const {
|
||||
return std::stoul(m_parts[1]);
|
||||
}
|
||||
|
||||
u32 SemanticVersion::patch() const {
|
||||
return std::stoul(m_parts[2]);
|
||||
}
|
||||
|
||||
bool SemanticVersion::nightly() const {
|
||||
return m_parts.size() == 4 && m_parts[3] == "WIP";
|
||||
}
|
||||
|
||||
const std::string& SemanticVersion::buildType() const {
|
||||
return m_buildType;
|
||||
}
|
||||
|
||||
|
||||
bool SemanticVersion::isValid() const {
|
||||
return !m_parts.empty();
|
||||
}
|
||||
|
||||
bool SemanticVersion::operator==(const SemanticVersion& other) const {
|
||||
return this->m_parts == other.m_parts;
|
||||
}
|
||||
|
||||
std::strong_ordering SemanticVersion::operator<=>(const SemanticVersion &other) const {
|
||||
if (*this == other)
|
||||
return std::strong_ordering::equivalent;
|
||||
|
||||
if (this->major() > other.major())
|
||||
return std::strong_ordering::greater;
|
||||
if (this->minor() > other.minor())
|
||||
return std::strong_ordering::greater;
|
||||
if (this->patch() > other.patch())
|
||||
return std::strong_ordering::greater;
|
||||
if (!this->nightly() && other.nightly())
|
||||
return std::strong_ordering::greater;
|
||||
|
||||
return std::strong_ordering::less;
|
||||
}
|
||||
|
||||
std::string SemanticVersion::get(bool withBuildType) const {
|
||||
auto result = wolv::util::combineStrings(m_parts, ".");
|
||||
|
||||
if (withBuildType && !m_buildType.empty())
|
||||
result += hex::format("-{}", m_buildType);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -331,9 +331,9 @@ namespace hex::init {
|
||||
// Draw version information
|
||||
// In debug builds, also display the current commit hash and branch
|
||||
#if defined(DEBUG)
|
||||
const static auto VersionInfo = hex::format("{0} : {1}@{2}", ImHexApi::System::getImHexVersion(), ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash());
|
||||
const static auto VersionInfo = hex::format("{0} : {1}@{2}", ImHexApi::System::getImHexVersion().get(), ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash());
|
||||
#else
|
||||
const static auto VersionInfo = hex::format("{0}", ImHexApi::System::getImHexVersion());
|
||||
const static auto VersionInfo = hex::format("{0}", ImHexApi::System::getImHexVersion().get());
|
||||
#endif
|
||||
|
||||
drawList->AddText(ImVec2((this->m_splashBackgroundTexture.getSize().x - ImGui::CalcTextSize(VersionInfo.c_str()).x) / 2, 105), ImColor(0xFF, 0xFF, 0xFF, 0xFF), VersionInfo.c_str());
|
||||
|
@ -40,7 +40,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
// Log some system information to aid debugging when users share their logs
|
||||
log::info("Welcome to ImHex {}!", ImHexApi::System::getImHexVersion());
|
||||
log::info("Welcome to ImHex {}!", ImHexApi::System::getImHexVersion().get());
|
||||
log::info("Compiled using commit {}@{}", ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash());
|
||||
log::info("Running on {} {} ({})", ImHexApi::System::getOSName(), ImHexApi::System::getOSVersion(), ImHexApi::System::getArchitecture());
|
||||
#if defined(OS_LINUX)
|
||||
|
@ -31,7 +31,7 @@ namespace hex::plugin::builtin {
|
||||
std::ignore = args;
|
||||
|
||||
hex::log::print(std::string(romfs::get("logo.ans").string()),
|
||||
ImHexApi::System::getImHexVersion(),
|
||||
ImHexApi::System::getImHexVersion().get(),
|
||||
ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash(),
|
||||
__DATE__, __TIME__,
|
||||
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed");
|
||||
|
@ -18,7 +18,7 @@ namespace hex::plugin::builtin {
|
||||
nlohmann::json result;
|
||||
|
||||
result["build"] = {
|
||||
{ "version", ImHexApi::System::getImHexVersion() },
|
||||
{ "version", ImHexApi::System::getImHexVersion().get() },
|
||||
{ "commit", ImHexApi::System::getCommitHash(true) },
|
||||
{ "branch", ImHexApi::System::getCommitBranch() }
|
||||
};
|
||||
|
@ -226,11 +226,15 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
EventWindowInitialized::subscribe([] {
|
||||
if (ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "") == "") {
|
||||
const auto currVersion = ImHexApi::System::getImHexVersion();
|
||||
const auto prevLaunchVersion = ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "");
|
||||
if (prevLaunchVersion == "") {
|
||||
EventFirstLaunch::post();
|
||||
}
|
||||
|
||||
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", ImHexApi::System::getImHexVersion());
|
||||
EventImHexUpdated::post(SemanticVersion(prevLaunchVersion), currVersion);
|
||||
|
||||
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", currVersion.get(false));
|
||||
});
|
||||
|
||||
EventWindowDeinitializing::subscribe([](GLFWwindow *window) {
|
||||
|
@ -39,9 +39,7 @@ namespace hex::plugin::builtin {
|
||||
return false;
|
||||
|
||||
// Convert the current version string to a format that can be compared to the latest release
|
||||
auto versionString = ImHexApi::System::getImHexVersion();
|
||||
size_t versionLength = std::min(versionString.find_first_of('-'), versionString.length());
|
||||
auto currVersion = "v" + versionString.substr(0, versionLength);
|
||||
auto currVersion = "v" + ImHexApi::System::getImHexVersion().get(false);
|
||||
|
||||
// Get the latest release version string
|
||||
auto latestVersion = releases["tag_name"].get<std::string_view>();
|
||||
@ -59,7 +57,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", uuid);
|
||||
}
|
||||
|
||||
TaskManager::createBackgroundTask("hex.builtin.task.sending_statistics"_lang, [uuid, versionString](auto&) {
|
||||
TaskManager::createBackgroundTask("hex.builtin.task.sending_statistics"_lang, [uuid](auto&) {
|
||||
// To avoid potentially flooding our database with lots of dead users
|
||||
// from people just visiting the website, don't send telemetry data from
|
||||
// the web version
|
||||
@ -71,7 +69,7 @@ namespace hex::plugin::builtin {
|
||||
nlohmann::json telemetry = {
|
||||
{ "uuid", uuid },
|
||||
{ "format_version", "1" },
|
||||
{ "imhex_version", versionString },
|
||||
{ "imhex_version", ImHexApi::System::getImHexVersion().get(false) },
|
||||
{ "imhex_commit", fmt::format("{}@{}", ImHexApi::System::getCommitHash(true), ImHexApi::System::getCommitBranch()) },
|
||||
{ "install_type", ImHexApi::System::isPortableVersion() ? "Portable" : "Installed" },
|
||||
{ "os", ImHexApi::System::getOSName() },
|
||||
|
@ -298,7 +298,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TextUnformatted("hex.builtin.oobe.server_contact.data_collected.version"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedWrapped("{}\n{}@{}\n{}",
|
||||
ImHexApi::System::getImHexVersion(),
|
||||
ImHexApi::System::getImHexVersion().get(),
|
||||
ImHexApi::System::getCommitHash(true),
|
||||
ImHexApi::System::getCommitBranch(),
|
||||
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed"
|
||||
|
@ -158,7 +158,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
{
|
||||
const auto metadataContent = hex::format("{}\n{}", MetadataHeaderMagic, ImHexApi::System::getImHexVersion());
|
||||
const auto metadataContent = hex::format("{}\n{}", MetadataHeaderMagic, ImHexApi::System::getImHexVersion().get(false));
|
||||
tar.writeString(MetadataPath, metadataContent);
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
// Draw basic information about ImHex and its version
|
||||
ImGuiExt::TextFormatted("ImHex Hex Editor v{} by WerWolv", ImHexApi::System::getImHexVersion());
|
||||
ImGuiExt::TextFormatted("ImHex Hex Editor v{} by WerWolv", ImHexApi::System::getImHexVersion().get());
|
||||
ImGui::Indent(25_scaled);
|
||||
ImGuiExt::TextFormatted("Powered by Dear ImGui v{}", ImGui::GetVersion());
|
||||
ImGui::Unindent(25_scaled);
|
||||
@ -582,9 +582,9 @@ namespace hex::plugin::builtin {
|
||||
static ReleaseNotes notes;
|
||||
|
||||
// Set up the request to get the release notes the first time the page is opened
|
||||
const static auto ImHexVersionString = ImHexApi::System::getImHexVersion(false);
|
||||
const static auto ImHexVersion = ImHexApi::System::getImHexVersion();
|
||||
AT_FIRST_TIME {
|
||||
static HttpRequest request("GET", GitHubApiURL + std::string("/releases/") + (ImHexVersionString.ends_with(".WIP") ? "latest" : ( "tags/v" + ImHexVersionString)));
|
||||
static HttpRequest request("GET", GitHubApiURL + std::string("/releases/") + (ImHexVersion.nightly() ? "latest" : ( "tags/v" + ImHexVersion.get(false))));
|
||||
|
||||
m_releaseNoteRequest = request.execute();
|
||||
};
|
||||
|
@ -57,7 +57,7 @@ namespace hex::plugin::builtin {
|
||||
// Force update all installed items after an update so that there's no old and incompatible versions around anymore
|
||||
{
|
||||
const auto prevUpdateVersion = ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "");
|
||||
if (prevUpdateVersion != ImHexApi::System::getImHexVersion()) {
|
||||
if (SemanticVersion(prevUpdateVersion) != ImHexApi::System::getImHexVersion()) {
|
||||
updateAll();
|
||||
}
|
||||
}
|
||||
@ -359,7 +359,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
TaskManager::doLater([] {
|
||||
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", ImHexApi::System::getImHexVersion());
|
||||
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", ImHexApi::System::getImHexVersion().get(false));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user