aboutsummaryrefslogtreecommitdiffstats
path: root/src/m_ver_check/SoftwareVersion.cpp
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2026-09-24 22:59:10 +0200
committersaturneric <[email protected]>2026-09-24 22:59:10 +0200
commit4249f0192baf88e33bfb4e47828279ae2b569a8d (patch)
tree5eea66cc8f58c6770c9777215a58c7be8f375e1b /src/m_ver_check/SoftwareVersion.cpp
parentdocs(README): document instant messaging module and UI actions (diff)
downloadmodules-4249f0192baf88e33bfb4e47828279ae2b569a8d.tar.gz
modules-4249f0192baf88e33bfb4e47828279ae2b569a8d.zip
feat(update): add robust GitHub update checking
- replace legacy provider tasks with an injectable update checker - track release, tag, and commit lookup results independently - preserve last known good results across failed refreshes - persist schema-versioned update state and reject stale formats - add update presentation logic and refresh the update dialog UI - remove provider selection in favor of GitHub Releases - add comprehensive release-checking and presentation tests
Diffstat (limited to 'src/m_ver_check/SoftwareVersion.cpp')
-rw-r--r--src/m_ver_check/SoftwareVersion.cpp114
1 files changed, 80 insertions, 34 deletions
diff --git a/src/m_ver_check/SoftwareVersion.cpp b/src/m_ver_check/SoftwareVersion.cpp
index ed74cb3..2184361 100644
--- a/src/m_ver_check/SoftwareVersion.cpp
+++ b/src/m_ver_check/SoftwareVersion.cpp
@@ -28,42 +28,102 @@
#include "SoftwareVersion.h"
-#include <GFModule.h>
-#include <GFSDKLog.h>
-
-#include <QJsonDocument>
#include <QJsonObject>
#include <QString>
+#include <array>
+#include <utility>
+
+namespace {
+
+// Names, not enum values, on disk: a reordered enum must not flip a cached
+// "not found" into "confirmed".
+constexpr std::array<std::pair<RemoteFact, const char*>, 3> kFactNames = {{
+ {RemoteFact::kUnknown, "unknown"},
+ {RemoteFact::kConfirmed, "confirmed"},
+ {RemoteFact::kNotFound, "not_found"},
+}};
+
+constexpr std::array<std::pair<ListOutcome, const char*>, 3> kListNames = {{
+ {ListOutcome::kFailed, "failed"},
+ {ListOutcome::kNoMatch, "no_match"},
+ {ListOutcome::kFound, "found"},
+}};
-auto SoftwareVersion::NeedUpgrade() const -> bool {
- return !latest_version.isEmpty() &&
- GFCompareSoftwareVersion(current_version.toUtf8().constData(),
- latest_version.toUtf8().constData()) < 0;
+template <typename Enum, std::size_t N>
+auto NameOf(const std::array<std::pair<Enum, const char*>, N>& names,
+ Enum value) -> QString {
+ for (const auto& [e, name] : names) {
+ if (e == value) return QString::fromLatin1(name);
+ }
+ return QString::fromLatin1(names.front().second);
}
-auto SoftwareVersion::VersionWithdrawn() const -> bool {
- return !latest_version.isEmpty() && !current_version_publish_in_remote;
+template <typename Enum, std::size_t N>
+auto ValueOf(const std::array<std::pair<Enum, const char*>, N>& names,
+ const QString& name) -> Enum {
+ for (const auto& [e, n] : names) {
+ if (name == QLatin1String(n)) return e;
+ }
+ return names.front().first;
}
-auto SoftwareVersion::CurrentVersionReleased() const -> bool {
- return !latest_version.isEmpty() && current_version_publish_in_remote;
+} // namespace
+
+auto SoftwareVersion::SameBuild(const QString& version,
+ const QString& commit) const -> bool {
+ return current_version == version && local_commit_hash == commit;
}
auto SoftwareVersion::ToJson() const -> QJsonObject {
+ QJsonObject latest;
+ latest["version"] = list.latest.version;
+ latest["published_at"] = list.latest.published_at;
+ latest["notes"] = list.latest.notes;
+ latest["html_url"] = list.latest.html_url;
+
QJsonObject obj;
- obj["api"] = api;
- obj["latest_version"] = latest_version;
+ obj["schema"] = kSchema;
obj["current_version"] = current_version;
- obj["current_version_publish_in_remote"] = current_version_publish_in_remote;
- obj["current_commit_hash_publish_in_remote"] =
- current_commit_hash_publish_in_remote;
- obj["publish_date"] = publish_date;
- obj["release_note"] = release_note;
obj["local_commit_hash"] = local_commit_hash;
- obj["timestamp"] = timestamp.toSecsSinceEpoch();
+ obj["list"] = NameOf(kListNames, list.outcome);
+ obj["latest"] = latest;
+ obj["tag_fact"] = NameOf(kFactNames, tag_fact);
+ obj["commit_fact"] = NameOf(kFactNames, commit_fact);
+ obj["complete"] = complete;
+ obj["checked_at"] = checked_at.toSecsSinceEpoch();
return obj;
}
+auto SoftwareVersion::FromJson(const QJsonObject& obj)
+ -> std::optional<SoftwareVersion> {
+ if (obj.value("schema").toInt() != kSchema) return std::nullopt;
+ if (!obj.value("checked_at").isDouble()) return std::nullopt;
+
+ SoftwareVersion sv;
+ sv.current_version = obj.value("current_version").toString();
+ sv.local_commit_hash = obj.value("local_commit_hash").toString();
+ sv.list.outcome = ValueOf(kListNames, obj.value("list").toString());
+
+ const auto latest = obj.value("latest").toObject();
+ sv.list.latest.version = latest.value("version").toString();
+ sv.list.latest.published_at = latest.value("published_at").toString();
+ sv.list.latest.notes = latest.value("notes").toString();
+ sv.list.latest.html_url = latest.value("html_url").toString();
+
+ sv.tag_fact = ValueOf(kFactNames, obj.value("tag_fact").toString());
+ sv.commit_fact = ValueOf(kFactNames, obj.value("commit_fact").toString());
+ sv.complete = obj.value("complete").toBool();
+ sv.checked_at =
+ QDateTime::fromSecsSinceEpoch(obj.value("checked_at").toInteger());
+
+ // A "found" list without a version is not something ToJson() writes.
+ if (sv.list.outcome == ListOutcome::kFound &&
+ sv.list.latest.version.isEmpty()) {
+ return std::nullopt;
+ }
+ return sv;
+}
+
auto SoftwareVersion::VersionSeries(const QString& version) -> QString {
if (version.isEmpty()) return {};
@@ -87,17 +147,3 @@ auto SoftwareVersion::SameSeries(const QString& a, const QString& b) -> bool {
auto series_a = VersionSeries(a);
return !series_a.isEmpty() && series_a == VersionSeries(b);
}
-
-void SoftwareVersion::FromJson(const QJsonObject& obj) {
- api = obj.value("api").toString();
- latest_version = obj.value("latest_version").toString();
- current_version = obj.value("current_version").toString();
- current_version_publish_in_remote =
- obj.value("current_version_publish_in_remote").toBool();
- current_commit_hash_publish_in_remote =
- obj.value("current_commit_hash_publish_in_remote").toBool();
- publish_date = obj.value("publish_date").toString();
- release_note = obj.value("release_note").toString();
- local_commit_hash = obj.value("local_commit_hash").toString();
- timestamp = QDateTime::fromSecsSinceEpoch(obj.value("timestamp").toInt());
-}