From 938f896bfa7775cf7dcf1ee6883572f514f53993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 4 Sep 2021 21:27:09 +0200 Subject: [PATCH] GH-4014 change updater to recognize new Qt 5.15.2 builds --- CMakeLists.txt | 2 +- buildconfig/BuildConfig.cpp.in | 4 +- buildconfig/BuildConfig.h | 2 +- launcher/MultiMC.cpp | 45 ++++++++++++++++++- launcher/minecraft/auth/flows/AuthContext.cpp | 2 +- launcher/pages/global/MultiMCPage.cpp | 3 +- launcher/updater/DownloadTask.cpp | 2 +- launcher/updater/UpdateChecker.cpp | 40 ++++++++++++----- launcher/updater/UpdateChecker.h | 4 +- libraries/systeminfo/include/sys.h | 14 ++++++ libraries/systeminfo/src/sys_apple.cpp | 22 ++++++++- libraries/systeminfo/src/sys_unix.cpp | 23 +++++++++- libraries/systeminfo/src/sys_win32.cpp | 4 ++ 13 files changed, 141 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index acc777fc..84c4a180 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number. set(MultiMC_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.") # Channel list URL -set(MultiMC_CHANLIST_URL "" CACHE STRING "URL for the channel list.") +set(MultiMC_UPDATER_BASE "" CACHE STRING "Base URL for the updater.") # Notification URL set(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.") diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index 60d417a6..d9f4d1f1 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -12,14 +12,14 @@ Config::Config() VERSION_BUILD = @MultiMC_VERSION_BUILD@; BUILD_PLATFORM = "@MultiMC_BUILD_PLATFORM@"; - CHANLIST_URL = "@MultiMC_CHANLIST_URL@"; + UPDATER_BASE = "@MultiMC_UPDATER_BASE@"; ANALYTICS_ID = "@MultiMC_ANALYTICS_ID@"; NOTIFICATION_URL = "@MultiMC_NOTIFICATION_URL@"; FULL_VERSION_STR = "@MultiMC_VERSION_MAJOR@.@MultiMC_VERSION_MINOR@.@MultiMC_VERSION_BUILD@"; GIT_COMMIT = "@MultiMC_GIT_COMMIT@"; GIT_REFSPEC = "@MultiMC_GIT_REFSPEC@"; - if(GIT_REFSPEC.startsWith("refs/heads/") && !CHANLIST_URL.isEmpty() && VERSION_BUILD >= 0) + if(GIT_REFSPEC.startsWith("refs/heads/") && !UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty() && VERSION_BUILD >= 0) { VERSION_CHANNEL = GIT_REFSPEC; VERSION_CHANNEL.remove("refs/heads/"); diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index de7d4b49..6a35d1b3 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -29,7 +29,7 @@ public: QString BUILD_PLATFORM; /// URL for the updater's channel - QString CHANLIST_URL; + QString UPDATER_BASE; /// User-Agent to use. QString USER_AGENT = "MultiMC/5.0"; diff --git a/launcher/MultiMC.cpp b/launcher/MultiMC.cpp index 5961a45d..69ba4ac5 100644 --- a/launcher/MultiMC.cpp +++ b/launcher/MultiMC.cpp @@ -91,7 +91,8 @@ using namespace Commandline; "This usually fixes the problem and you can move the application elsewhere afterwards.\n"\ "\n" -static void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +namespace { +void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { const char *levels = "DWCFIS"; const QString format("%1 %2 %3\n"); @@ -111,6 +112,43 @@ static void appDebugOutput(QtMsgType type, const QMessageLogContext &context, co fflush(stderr); } +QString getIdealPlatform(QString currentPlatform) { + auto info = Sys::getKernelInfo(); + switch(info.kernelType) { + case Sys::KernelType::Darwin: { + if(info.kernelMajor >= 17) { + // macOS 10.13 or newer + return "osx64-5.15.2"; + } + else { + // macOS 10.12 or older + return "osx64"; + } + } + case Sys::KernelType::Windows: { + if(info.kernelMajor == 6 && info.kernelMinor >= 1) { + // Windows 7 + return "win32-5.15.2"; + } + else if (info.kernelMajor > 6) { + // Above Windows 7 + return "win32-5.15.2"; + } + else { + // Below Windows 7 + return "win32"; + } + } + case Sys::KernelType::Undetermined: + case Sys::KernelType::Linux: { + break; + } + } + return currentPlatform; +} + +} + MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 @@ -678,7 +716,10 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) // initialize the updater if(BuildConfig.UPDATER_ENABLED) { - m_updateChecker.reset(new UpdateChecker(BuildConfig.CHANLIST_URL, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD)); + auto platform = getIdealPlatform(BuildConfig.BUILD_PLATFORM); + auto channelUrl = BuildConfig.UPDATER_BASE + platform + "/channels.json"; + qDebug() << "Initializing updater with platform: " << platform << " -- " << channelUrl; + m_updateChecker.reset(new UpdateChecker(channelUrl, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD)); qDebug() << "<> Updater started."; } diff --git a/launcher/minecraft/auth/flows/AuthContext.cpp b/launcher/minecraft/auth/flows/AuthContext.cpp index 1203dc5f..776f45fe 100644 --- a/launcher/minecraft/auth/flows/AuthContext.cpp +++ b/launcher/minecraft/auth/flows/AuthContext.cpp @@ -538,7 +538,7 @@ void AuthContext::onSTSAuthGenericDone( } Katabasis::Token temp; - if(!parseXTokenResponse(replyData, temp, "STSAuthGaneric")) { + if(!parseXTokenResponse(replyData, temp, "STSAuthGeneric")) { qWarning() << "Could not parse authorization response for access to xbox API..."; failResult(m_xboxProfileSucceeded); return; diff --git a/launcher/pages/global/MultiMCPage.cpp b/launcher/pages/global/MultiMCPage.cpp index d383e6ed..5d43b187 100644 --- a/launcher/pages/global/MultiMCPage.cpp +++ b/launcher/pages/global/MultiMCPage.cpp @@ -58,8 +58,7 @@ MultiMCPage::MultiMCPage(QWidget *parent) : QWidget(parent), ui(new Ui::MultiMCP if(BuildConfig.UPDATER_ENABLED) { - QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this, - &MultiMCPage::refreshUpdateChannelList); + QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this, &MultiMCPage::refreshUpdateChannelList); if (MMC->updateChecker()->hasChannels()) { diff --git a/launcher/updater/DownloadTask.cpp b/launcher/updater/DownloadTask.cpp index 20b26ebb..2c62ad24 100644 --- a/launcher/updater/DownloadTask.cpp +++ b/launcher/updater/DownloadTask.cpp @@ -170,4 +170,4 @@ OperationList DownloadTask::operations() return m_operations; } -} \ No newline at end of file +} diff --git a/launcher/updater/UpdateChecker.cpp b/launcher/updater/UpdateChecker.cpp index be33c73c..eea73dcf 100644 --- a/launcher/updater/UpdateChecker.cpp +++ b/launcher/updater/UpdateChecker.cpp @@ -23,9 +23,12 @@ #define API_VERSION 0 #define CHANLIST_FORMAT 0 -UpdateChecker::UpdateChecker(QString channelListUrl, QString currentChannel, int currentBuild) +#include "BuildConfig.h" +#include "sys.h" + +UpdateChecker::UpdateChecker(QString channelUrl, QString currentChannel, int currentBuild) { - m_channelListUrl = channelListUrl; + m_channelUrl = channelUrl; m_currentChannel = currentChannel; m_currentBuild = currentBuild; } @@ -48,8 +51,7 @@ void UpdateChecker::checkForUpdate(QString updateChannel, bool notifyNoUpdate) // later. if (!m_chanListLoaded) { - qDebug() << "Channel list isn't loaded yet. Loading channel list and deferring " - "update check."; + qDebug() << "Channel list isn't loaded yet. Loading channel list and deferring update check."; m_checkUpdateWaiting = true; m_deferredUpdateChannel = updateChannel; updateChanList(notifyNoUpdate); @@ -62,29 +64,43 @@ void UpdateChecker::checkForUpdate(QString updateChannel, bool notifyNoUpdate) return; } - m_updateChecking = true; - // Find the desired channel within the channel list and get its repo URL. If if cannot be // found, error. + QString stableUrl; m_newRepoUrl = ""; for (ChannelListEntry entry : m_channels) { - if (entry.id == updateChannel) + qDebug() << "channelEntry = " << entry.id; + if(entry.id == "stable") { + stableUrl = entry.url; + } + if (entry.id == updateChannel) { m_newRepoUrl = entry.url; - if (entry.id == m_currentChannel) + qDebug() << "is intended update channel: " << entry.id; + } + if (entry.id == m_currentChannel) { m_currentRepoUrl = entry.url; + qDebug() << "is current update channel: " << entry.id; + } } qDebug() << "m_repoUrl = " << m_newRepoUrl; - // If we didn't find our channel, error. + if (m_newRepoUrl.isEmpty()) { + qWarning() << "m_repoUrl was empty. defaulting to 'stable': " << stableUrl; + m_newRepoUrl = stableUrl; + } + + // If nothing applies, error if (m_newRepoUrl.isEmpty()) { - qCritical() << "m_repoUrl is empty!"; + qCritical() << "failed to select any update repository for: " << updateChannel; emit updateCheckFailed(); return; } + m_updateChecking = true; + QUrl indexUrl = QUrl(m_newRepoUrl).resolved(QUrl("index.json")); auto job = new NetJob("GoUpdate Repository Index"); @@ -174,7 +190,7 @@ void UpdateChecker::updateChanList(bool notifyNoUpdate) return; } - if (m_channelListUrl.isEmpty()) + if (m_channelUrl.isEmpty()) { qCritical() << "Failed to update channel list. No channel list URL set." << "If you'd like to use MultiMC's update system, please pass the channel " @@ -184,7 +200,7 @@ void UpdateChecker::updateChanList(bool notifyNoUpdate) m_chanListLoading = true; NetJob *job = new NetJob("Update System Channel List"); - job->addNetAction(Net::Download::makeByteArray(QUrl(m_channelListUrl), &chanlistData)); + job->addNetAction(Net::Download::makeByteArray(QUrl(m_channelUrl), &chanlistData)); connect(job, &NetJob::succeeded, [this, notifyNoUpdate]() { chanListDownloadFinished(notifyNoUpdate); }); QObject::connect(job, &NetJob::failed, this, &UpdateChecker::chanListDownloadFailed); chanListJob.reset(job); diff --git a/launcher/updater/UpdateChecker.h b/launcher/updater/UpdateChecker.h index 91b6e26e..219c3c62 100644 --- a/launcher/updater/UpdateChecker.h +++ b/launcher/updater/UpdateChecker.h @@ -23,7 +23,7 @@ class UpdateChecker : public QObject Q_OBJECT public: - UpdateChecker(QString channelListUrl, QString currentChannel, int currentBuild); + UpdateChecker(QString channelUrl, QString currentChannel, int currentBuild); void checkForUpdate(QString updateChannel, bool notifyNoUpdate); /*! @@ -78,7 +78,7 @@ private: NetJobPtr chanListJob; QByteArray chanlistData; - QString m_channelListUrl; + QString m_channelUrl; QList m_channels; diff --git a/libraries/systeminfo/include/sys.h b/libraries/systeminfo/include/sys.h index 914d2555..bd6e2486 100644 --- a/libraries/systeminfo/include/sys.h +++ b/libraries/systeminfo/include/sys.h @@ -4,10 +4,24 @@ namespace Sys { const uint64_t mebibyte = 1024ull * 1024ull; + +enum class KernelType { + Undetermined, + Windows, + Darwin, + Linux +}; + struct KernelInfo { QString kernelName; QString kernelVersion; + + KernelType kernelType = KernelType::Undetermined; + int kernelMajor = 0; + int kernelMinor = 0; + int kernelPatch = 0; + bool isCursed = false; }; KernelInfo getKernelInfo(); diff --git a/libraries/systeminfo/src/sys_apple.cpp b/libraries/systeminfo/src/sys_apple.cpp index 4bcffae4..2d7d6083 100644 --- a/libraries/systeminfo/src/sys_apple.cpp +++ b/libraries/systeminfo/src/sys_apple.cpp @@ -2,13 +2,33 @@ #include +#include +#include + Sys::KernelInfo Sys::getKernelInfo() { Sys::KernelInfo out; struct utsname buf; uname(&buf); + out.kernelType = KernelType::Darwin; out.kernelName = buf.sysname; - out.kernelVersion = buf.release; + QString release = out.kernelVersion = buf.release; + + // TODO: figure out how to detect cursed-ness (macOS emulated on linux via mad hacks and so on) + out.isCursed = false; + + out.kernelMajor = 0; + out.kernelMinor = 0; + out.kernelPatch = 0; + auto sections = release.split('-'); + if(sections.size() >= 1) { + auto versionParts = sections[0].split('.'); + if(sections.size() >= 3) { + out.kernelMajor = sections[0].toInt(); + out.kernelMinor = sections[1].toInt(); + out.kernelPatch = sections[2].toInt(); + } + } return out; } diff --git a/libraries/systeminfo/src/sys_unix.cpp b/libraries/systeminfo/src/sys_unix.cpp index 42c0d319..303ead1f 100644 --- a/libraries/systeminfo/src/sys_unix.cpp +++ b/libraries/systeminfo/src/sys_unix.cpp @@ -6,13 +6,34 @@ #include #include +#include +#include + Sys::KernelInfo Sys::getKernelInfo() { Sys::KernelInfo out; struct utsname buf; uname(&buf); + // NOTE: we assume linux here. this needs further elaboration + out.kernelType = KernelType::Linux; out.kernelName = buf.sysname; - out.kernelVersion = buf.release; + QString release = out.kernelVersion = buf.release; + + // linux binary running on WSL is cursed. + out.isCursed = release.contains("WSL", Qt::CaseInsensitive) || release.contains("Microsoft", Qt::CaseInsensitive); + + out.kernelMajor = 0; + out.kernelMinor = 0; + out.kernelPatch = 0; + auto sections = release.split('-'); + if(sections.size() >= 1) { + auto versionParts = sections[0].split('.'); + if(sections.size() >= 3) { + out.kernelMajor = sections[0].toInt(); + out.kernelMinor = sections[1].toInt(); + out.kernelPatch = sections[2].toInt(); + } + } return out; } diff --git a/libraries/systeminfo/src/sys_win32.cpp b/libraries/systeminfo/src/sys_win32.cpp index a750b3a7..430b87e4 100644 --- a/libraries/systeminfo/src/sys_win32.cpp +++ b/libraries/systeminfo/src/sys_win32.cpp @@ -5,12 +5,16 @@ Sys::KernelInfo Sys::getKernelInfo() { Sys::KernelInfo out; + out.kernelType = KernelType::Windows; out.kernelName = "Windows"; OSVERSIONINFOW osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOW)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); GetVersionExW(&osvi); out.kernelVersion = QString("%1.%2").arg(osvi.dwMajorVersion).arg(osvi.dwMinorVersion); + out.kernelMajor = osvi.dwMajorVersion; + out.kernelMinor = osvi.dwMinorVersion; + out.kernelPatch = osvi.dwBuildNumber; return out; }