From 6aa9bd0f77dcb5128167fae62e32aa5252fe85c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 2 Dec 2013 00:55:24 +0100 Subject: Renew the updater branch Now with some actual consensus on what the updater will do! --- CMakeLists.txt | 51 +- MultiMC.cpp | 4 + MultiMC.h | 7 + config.h.in | 20 +- gui/MainWindow.cpp | 29 + gui/MainWindow.h | 2 + gui/dialogs/UpdateDialog.cpp | 28 + gui/dialogs/UpdateDialog.h | 46 + gui/dialogs/UpdateDialog.ui | 63 + logic/GoUpdate.cpp | 99 + logic/GoUpdate.h | 43 + mmc_updater/CMakeLists.txt | 44 + mmc_updater/LICENSE | 19 + mmc_updater/README.md | 138 + .../cmake/modules/GenerateCppResourceFile.cmake | 23 + mmc_updater/depends/AnyOption/CMakeLists.txt | 9 + mmc_updater/depends/AnyOption/README | 16 + mmc_updater/depends/AnyOption/anyoption.cpp | 1176 ++++++ mmc_updater/depends/AnyOption/anyoption.h | 270 ++ mmc_updater/depends/tinyxml/CMakeLists.txt | 24 + mmc_updater/depends/tinyxml/readme.txt | 530 +++ mmc_updater/depends/tinyxml/tinystr.cpp | 111 + mmc_updater/depends/tinyxml/tinystr.h | 305 ++ mmc_updater/depends/tinyxml/tinyxml.cpp | 1886 +++++++++ mmc_updater/depends/tinyxml/tinyxml.h | 1805 +++++++++ mmc_updater/depends/tinyxml/tinyxmlerror.cpp | 52 + mmc_updater/depends/tinyxml/tinyxmlparser.cpp | 1638 ++++++++ mmc_updater/depends/win32cpp/controls.h | 1074 +++++ mmc_updater/depends/win32cpp/copyright.txt | 33 + mmc_updater/depends/win32cpp/cstring.h | 905 +++++ mmc_updater/depends/win32cpp/default_resource.h | 94 + mmc_updater/depends/win32cpp/default_resource.rc | 250 ++ mmc_updater/depends/win32cpp/dialog.h | 876 ++++ mmc_updater/depends/win32cpp/docking.h | 4214 ++++++++++++++++++++ mmc_updater/depends/win32cpp/file.h | 392 ++ mmc_updater/depends/win32cpp/frame.h | 3303 +++++++++++++++ mmc_updater/depends/win32cpp/gdi.h | 3944 ++++++++++++++++++ mmc_updater/depends/win32cpp/info.txt | 205 + mmc_updater/depends/win32cpp/listview.h | 867 ++++ mmc_updater/depends/win32cpp/mdi.h | 783 ++++ mmc_updater/depends/win32cpp/menu.h | 600 +++ mmc_updater/depends/win32cpp/propertysheet.h | 960 +++++ mmc_updater/depends/win32cpp/rebar.h | 709 ++++ mmc_updater/depends/win32cpp/release notes.txt | 116 + mmc_updater/depends/win32cpp/ribbon.h | 527 +++ mmc_updater/depends/win32cpp/shared_ptr.h | 199 + mmc_updater/depends/win32cpp/socket.h | 778 ++++ mmc_updater/depends/win32cpp/statusbar.h | 226 ++ mmc_updater/depends/win32cpp/stdcontrols.h | 1000 +++++ mmc_updater/depends/win32cpp/tab.h | 1658 ++++++++ mmc_updater/depends/win32cpp/taskdialog.h | 811 ++++ mmc_updater/depends/win32cpp/thread.h | 241 ++ mmc_updater/depends/win32cpp/toolbar.h | 1361 +++++++ mmc_updater/depends/win32cpp/treeview.h | 624 +++ mmc_updater/depends/win32cpp/wceframe.h | 420 ++ mmc_updater/depends/win32cpp/wcestddef.h | 58 + mmc_updater/depends/win32cpp/webbrowser.h | 760 ++++ mmc_updater/depends/win32cpp/wincore.h | 2977 ++++++++++++++ mmc_updater/depends/win32cpp/winutils.h | 649 +++ mmc_updater/src/AppInfo.cpp | 23 + mmc_updater/src/AppInfo.h | 39 + mmc_updater/src/CMakeLists.txt | 121 + mmc_updater/src/DirIterator.cpp | 85 + mmc_updater/src/DirIterator.h | 43 + mmc_updater/src/FileUtils.cpp | 557 +++ mmc_updater/src/FileUtils.h | 141 + mmc_updater/src/Log.cpp | 65 + mmc_updater/src/Log.h | 46 + mmc_updater/src/MacBundle.cpp | 53 + mmc_updater/src/MacBundle.h | 35 + mmc_updater/src/Platform.h | 30 + mmc_updater/src/ProcessUtils.cpp | 536 +++ mmc_updater/src/ProcessUtils.h | 97 + mmc_updater/src/StandardDirs.cpp | 63 + mmc_updater/src/StandardDirs.h | 22 + mmc_updater/src/StandardDirs.mm | 18 + mmc_updater/src/StlSymbolsLeopard.cpp | 75 + mmc_updater/src/StringUtils.h | 46 + mmc_updater/src/UpdateDialog.cpp | 25 + mmc_updater/src/UpdateDialog.h | 29 + mmc_updater/src/UpdateDialogAscii.cpp | 70 + mmc_updater/src/UpdateDialogAscii.h | 32 + mmc_updater/src/UpdateDialogCocoa.h | 32 + mmc_updater/src/UpdateDialogCocoa.mm | 194 + mmc_updater/src/UpdateDialogGtk.cpp | 155 + mmc_updater/src/UpdateDialogGtk.h | 42 + mmc_updater/src/UpdateDialogGtkFactory.cpp | 59 + mmc_updater/src/UpdateDialogGtkFactory.h | 13 + mmc_updater/src/UpdateDialogWin32.cpp | 215 + mmc_updater/src/UpdateDialogWin32.h | 39 + mmc_updater/src/UpdateInstaller.cpp | 439 ++ mmc_updater/src/UpdateInstaller.h | 70 + mmc_updater/src/UpdateMessage.h | 42 + mmc_updater/src/UpdateObserver.h | 15 + mmc_updater/src/UpdateScript.cpp | 98 + mmc_updater/src/UpdateScript.h | 86 + mmc_updater/src/UpdaterOptions.cpp | 156 + mmc_updater/src/UpdaterOptions.h | 27 + mmc_updater/src/main.cpp | 201 + mmc_updater/src/resources/Info.plist | 38 + mmc_updater/src/resources/icon128.png | Bin 0 -> 3802 bytes mmc_updater/src/resources/icon64.png | Bin 0 -> 2182 bytes mmc_updater/src/resources/mac.icns | Bin 0 -> 43606 bytes mmc_updater/src/resources/updater.ico | Bin 0 -> 82726 bytes mmc_updater/src/resources/updater.rc | 30 + mmc_updater/src/tests/CMakeLists.txt | 51 + mmc_updater/src/tests/TestFileUtils.cpp | 50 + mmc_updater/src/tests/TestFileUtils.h | 10 + mmc_updater/src/tests/TestUpdateScript.cpp | 48 + mmc_updater/src/tests/TestUpdateScript.h | 9 + mmc_updater/src/tests/TestUpdaterOptions.cpp | 68 + mmc_updater/src/tests/TestUpdaterOptions.h | 8 + mmc_updater/src/tests/TestUtils.h | 108 + mmc_updater/src/tests/file_list.xml | 52 + mmc_updater/src/tests/new_app.cpp | 8 + mmc_updater/src/tests/old_app.cpp | 7 + mmc_updater/src/tests/test-update.rb | 218 + mmc_updater/src/tests/v2_file_list.xml | 67 + 118 files changed, 44913 insertions(+), 45 deletions(-) create mode 100644 gui/dialogs/UpdateDialog.cpp create mode 100644 gui/dialogs/UpdateDialog.h create mode 100644 gui/dialogs/UpdateDialog.ui create mode 100644 logic/GoUpdate.cpp create mode 100644 logic/GoUpdate.h create mode 100644 mmc_updater/CMakeLists.txt create mode 100644 mmc_updater/LICENSE create mode 100644 mmc_updater/README.md create mode 100644 mmc_updater/cmake/modules/GenerateCppResourceFile.cmake create mode 100644 mmc_updater/depends/AnyOption/CMakeLists.txt create mode 100644 mmc_updater/depends/AnyOption/README create mode 100644 mmc_updater/depends/AnyOption/anyoption.cpp create mode 100644 mmc_updater/depends/AnyOption/anyoption.h create mode 100644 mmc_updater/depends/tinyxml/CMakeLists.txt create mode 100644 mmc_updater/depends/tinyxml/readme.txt create mode 100644 mmc_updater/depends/tinyxml/tinystr.cpp create mode 100644 mmc_updater/depends/tinyxml/tinystr.h create mode 100644 mmc_updater/depends/tinyxml/tinyxml.cpp create mode 100644 mmc_updater/depends/tinyxml/tinyxml.h create mode 100644 mmc_updater/depends/tinyxml/tinyxmlerror.cpp create mode 100644 mmc_updater/depends/tinyxml/tinyxmlparser.cpp create mode 100644 mmc_updater/depends/win32cpp/controls.h create mode 100644 mmc_updater/depends/win32cpp/copyright.txt create mode 100644 mmc_updater/depends/win32cpp/cstring.h create mode 100644 mmc_updater/depends/win32cpp/default_resource.h create mode 100644 mmc_updater/depends/win32cpp/default_resource.rc create mode 100644 mmc_updater/depends/win32cpp/dialog.h create mode 100644 mmc_updater/depends/win32cpp/docking.h create mode 100644 mmc_updater/depends/win32cpp/file.h create mode 100644 mmc_updater/depends/win32cpp/frame.h create mode 100644 mmc_updater/depends/win32cpp/gdi.h create mode 100644 mmc_updater/depends/win32cpp/info.txt create mode 100644 mmc_updater/depends/win32cpp/listview.h create mode 100644 mmc_updater/depends/win32cpp/mdi.h create mode 100644 mmc_updater/depends/win32cpp/menu.h create mode 100644 mmc_updater/depends/win32cpp/propertysheet.h create mode 100644 mmc_updater/depends/win32cpp/rebar.h create mode 100644 mmc_updater/depends/win32cpp/release notes.txt create mode 100644 mmc_updater/depends/win32cpp/ribbon.h create mode 100644 mmc_updater/depends/win32cpp/shared_ptr.h create mode 100644 mmc_updater/depends/win32cpp/socket.h create mode 100644 mmc_updater/depends/win32cpp/statusbar.h create mode 100644 mmc_updater/depends/win32cpp/stdcontrols.h create mode 100644 mmc_updater/depends/win32cpp/tab.h create mode 100644 mmc_updater/depends/win32cpp/taskdialog.h create mode 100644 mmc_updater/depends/win32cpp/thread.h create mode 100644 mmc_updater/depends/win32cpp/toolbar.h create mode 100644 mmc_updater/depends/win32cpp/treeview.h create mode 100644 mmc_updater/depends/win32cpp/wceframe.h create mode 100644 mmc_updater/depends/win32cpp/wcestddef.h create mode 100644 mmc_updater/depends/win32cpp/webbrowser.h create mode 100644 mmc_updater/depends/win32cpp/wincore.h create mode 100644 mmc_updater/depends/win32cpp/winutils.h create mode 100644 mmc_updater/src/AppInfo.cpp create mode 100644 mmc_updater/src/AppInfo.h create mode 100644 mmc_updater/src/CMakeLists.txt create mode 100644 mmc_updater/src/DirIterator.cpp create mode 100644 mmc_updater/src/DirIterator.h create mode 100644 mmc_updater/src/FileUtils.cpp create mode 100644 mmc_updater/src/FileUtils.h create mode 100644 mmc_updater/src/Log.cpp create mode 100644 mmc_updater/src/Log.h create mode 100644 mmc_updater/src/MacBundle.cpp create mode 100644 mmc_updater/src/MacBundle.h create mode 100644 mmc_updater/src/Platform.h create mode 100644 mmc_updater/src/ProcessUtils.cpp create mode 100644 mmc_updater/src/ProcessUtils.h create mode 100644 mmc_updater/src/StandardDirs.cpp create mode 100644 mmc_updater/src/StandardDirs.h create mode 100644 mmc_updater/src/StandardDirs.mm create mode 100644 mmc_updater/src/StlSymbolsLeopard.cpp create mode 100644 mmc_updater/src/StringUtils.h create mode 100644 mmc_updater/src/UpdateDialog.cpp create mode 100644 mmc_updater/src/UpdateDialog.h create mode 100644 mmc_updater/src/UpdateDialogAscii.cpp create mode 100644 mmc_updater/src/UpdateDialogAscii.h create mode 100644 mmc_updater/src/UpdateDialogCocoa.h create mode 100644 mmc_updater/src/UpdateDialogCocoa.mm create mode 100644 mmc_updater/src/UpdateDialogGtk.cpp create mode 100644 mmc_updater/src/UpdateDialogGtk.h create mode 100644 mmc_updater/src/UpdateDialogGtkFactory.cpp create mode 100644 mmc_updater/src/UpdateDialogGtkFactory.h create mode 100644 mmc_updater/src/UpdateDialogWin32.cpp create mode 100644 mmc_updater/src/UpdateDialogWin32.h create mode 100644 mmc_updater/src/UpdateInstaller.cpp create mode 100644 mmc_updater/src/UpdateInstaller.h create mode 100644 mmc_updater/src/UpdateMessage.h create mode 100644 mmc_updater/src/UpdateObserver.h create mode 100644 mmc_updater/src/UpdateScript.cpp create mode 100644 mmc_updater/src/UpdateScript.h create mode 100644 mmc_updater/src/UpdaterOptions.cpp create mode 100644 mmc_updater/src/UpdaterOptions.h create mode 100644 mmc_updater/src/main.cpp create mode 100644 mmc_updater/src/resources/Info.plist create mode 100644 mmc_updater/src/resources/icon128.png create mode 100644 mmc_updater/src/resources/icon64.png create mode 100644 mmc_updater/src/resources/mac.icns create mode 100644 mmc_updater/src/resources/updater.ico create mode 100644 mmc_updater/src/resources/updater.rc create mode 100644 mmc_updater/src/tests/CMakeLists.txt create mode 100644 mmc_updater/src/tests/TestFileUtils.cpp create mode 100644 mmc_updater/src/tests/TestFileUtils.h create mode 100644 mmc_updater/src/tests/TestUpdateScript.cpp create mode 100644 mmc_updater/src/tests/TestUpdateScript.h create mode 100644 mmc_updater/src/tests/TestUpdaterOptions.cpp create mode 100644 mmc_updater/src/tests/TestUpdaterOptions.h create mode 100644 mmc_updater/src/tests/TestUtils.h create mode 100644 mmc_updater/src/tests/file_list.xml create mode 100644 mmc_updater/src/tests/new_app.cpp create mode 100644 mmc_updater/src/tests/old_app.cpp create mode 100755 mmc_updater/src/tests/test-update.rb create mode 100644 mmc_updater/src/tests/v2_file_list.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 79a69225..95b1c18f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,9 @@ include_directories(${LIBSETTINGS_INCLUDE_DIR}) add_subdirectory(depends/groupview) include_directories(${LIBGROUPVIEW_INCLUDE_DIR}) +# Add the updater +add_subdirectory(mmc_updater) + ################################ SET UP BUILD OPTIONS ################################ ######## Check endianness ######## @@ -129,10 +132,10 @@ ENDIF () MESSAGE(STATUS "MultiMC 5 version ${MultiMC_VERSION_STRING}") -# Custom target to just print the version. +#### Custom target to just print the version. ADD_CUSTOM_TARGET(version echo "Version: ${MultiMC_VERSION_STRING}") -# Check the current Git commit +#### Check the current Git commit execute_process(COMMAND git rev-parse HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} RESULT_VARIABLE GIT_COMMIT_CHECK_RESULTVAR @@ -140,7 +143,6 @@ execute_process(COMMAND git rev-parse HEAD OUTPUT_STRIP_TRAILING_WHITESPACE ) -# If Git executed successfully IF(GIT_COMMIT_CHECK_RESULTVAR EQUAL 0) SET(MultiMC_GIT_COMMIT "${GIT_COMMIT_CHECK_OUTVAR}") MESSAGE(STATUS "Git commit: ${MultiMC_GIT_COMMIT}") @@ -149,41 +151,12 @@ ELSE() MESSAGE(STATUS "Failed to check Git commit. ${GIT_COMMIT_CHECK_RESULTVAR}") ENDIF() - -######## Set Jenkins info ######## -# Jenkins build tag -IF(DEFINED MultiMC_BUILD_TAG) - MESSAGE(STATUS "Build tag: ${MultiMC_BUILD_TAG}") -ELSE() - MESSAGE(STATUS "No build tag specified.") - SET(MultiMC_BUILD_TAG custom) -ENDIF() - -# Architecture detection -IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(MultiMC_ARCH "x64" CACHE STRING "Architecture we're building for.") -ELSE() - SET(MultiMC_ARCH "x86" CACHE STRING "Architecture we're building for.") -ENDIF() -MESSAGE(STATUS "Architecture is ${MultiMC_ARCH}") - -# Jenkins job name -IF(WIN32) - SET(MultiMC_JOB_NAME "MultiMC5Windows" CACHE STRING "Jenkins job name.") -ELSEIF(UNIX AND APPLE) - SET(MultiMC_JOB_NAME "MultiMC5OSX" CACHE STRING "Jenkins job name.") -ELSE() - SET(MultiMC_JOB_NAME "MultiMC5Linux" CACHE STRING "Jenkins job name.") -ENDIF() - -# Jenkins URL -SET(MultiMC_JOB_URL "http://ci.forkk.net/job/${MultiMC_JOB_NAME}/arch=${MultiMC_ARCH}${MultiMC_Extra_Label}/" - CACHE STRING "URL of the jenkins job to pull updates from.") -MESSAGE(STATUS "Job URL: ${MultiMC_JOB_URL}") +#### GoUpdate URL +SET(MultiMC_REPO_BASE_URL "invalid" CACHE STRING "Base URL for the updater.") +SET(MultiMC_VERSION_BRANCH "invalid" CACHE STRING "URL of the stable update repo.") ######## Configure header ######## -configure_file("${PROJECT_SOURCE_DIR}/config.h.in" - "${PROJECT_BINARY_DIR}/include/config.h") +configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/include/config.h") ######## Other Stuff ######## @@ -251,6 +224,8 @@ gui/dialogs/AccountListDialog.h gui/dialogs/AccountListDialog.cpp gui/dialogs/AccountSelectDialog.h gui/dialogs/AccountSelectDialog.cpp +gui/dialogs/UpdateDialog.h +gui/dialogs/UpdateDialog.cpp # GUI - widgets gui/widgets/InstanceDelegate.h @@ -383,7 +358,8 @@ logic/NagUtils.h logic/NagUtils.cpp logic/SkinUtils.h logic/SkinUtils.cpp - +logic/GoUpdate.h +logic/GoUpdate.cpp ) @@ -410,6 +386,7 @@ gui/dialogs/EditNotesDialog.ui gui/dialogs/AccountListDialog.ui gui/dialogs/AccountSelectDialog.ui gui/dialogs/EditAccountDialog.ui +gui/dialogs/UpdateDialog.ui # Widgets/other gui/widgets/MCModInfoFrame.ui diff --git a/MultiMC.cpp b/MultiMC.cpp index e10292ab..3df73c18 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -20,6 +20,7 @@ #include "logic/net/HttpMetaCache.h" #include "logic/JavaUtils.h" +#include "logic/GoUpdate.h" #include "pathutils.h" #include "cmdutils.h" @@ -138,6 +139,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv), // load settings initGlobalSettings(); + // initialize the updater + m_go_update.reset(new GoUpdate()); + // and instances auto InstDirSetting = m_settings->getSetting("InstanceDir"); m_instances.reset(new InstanceList(InstDirSetting->get().toString(), this)); diff --git a/MultiMC.h b/MultiMC.h index cae6eee0..0ab7a8b5 100644 --- a/MultiMC.h +++ b/MultiMC.h @@ -17,6 +17,7 @@ class IconList; class QNetworkAccessManager; class ForgeVersionList; class JavaVersionList; +class GoUpdate; #if defined(MMC) #undef MMC @@ -84,6 +85,11 @@ public: return m_metacache; } + std::shared_ptr goupdate() + { + return m_go_update; + } + std::shared_ptr lwjgllist(); std::shared_ptr forgelist(); @@ -106,6 +112,7 @@ private: std::shared_ptr m_mmc_translator; std::shared_ptr m_settings; std::shared_ptr m_instances; + std::shared_ptr m_go_update; std::shared_ptr m_accounts; std::shared_ptr m_icons; std::shared_ptr m_qnam; diff --git a/config.h.in b/config.h.in index 34841817..26c8b1e9 100644 --- a/config.h.in +++ b/config.h.in @@ -1,16 +1,20 @@ +// Minor and major version, used to communicate changes to users. #define VERSION_MAJOR @MultiMC_VERSION_MAJOR@ #define VERSION_MINOR @MultiMC_VERSION_MINOR@ + +// Build number and type -- numer is used by the updater, type is purely visual #define VERSION_BUILD @MultiMC_VERSION_BUILD@ #define VERSION_BUILD_TYPE "@MultiMC_VERSION_BUILD_TYPE@" -#define GIT_COMMIT "@MultiMC_GIT_COMMIT@" - -#define VERSION_STR "@MultiMC_VERSION_STRING@" - -#define x86 1 -#define x64 2 +// URL base for the updater +#define VERSION_REPO "@MultiMC_REPO_BASE_URL@" -#define ARCH @MultiMC_ARCH@ +// The branch used for this build. User can switch between 'stable' and 'develop' +// if this is one of them. Otherwise, it pulls only from this one. +#define VERSION_BRANCH "@MultiMC_VERSION_BRANCH@" -#define USE_HTTPS @MultiMC_USE_HTTPS@ +// the commit hash of this build +#define GIT_COMMIT "@MultiMC_GIT_COMMIT@" +// This is printed on start to standard output +#define VERSION_STR "@MultiMC_VERSION_STRING@" diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 854091c6..a6796a29 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -59,6 +59,7 @@ #include "gui/dialogs/CopyInstanceDialog.h" #include "gui/dialogs/AccountListDialog.h" #include "gui/dialogs/AccountSelectDialog.h" +#include "gui/dialogs/UpdateDialog.h" #include "gui/dialogs/EditAccountDialog.h" #include "gui/ConsoleWindow.h" @@ -83,6 +84,7 @@ #include "logic/SkinUtils.h" #include "logic/LegacyInstance.h" +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { @@ -236,6 +238,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi MMC->lwjgllist()->loadList(); } + // set up the updater object. + auto updater = MMC->goupdate(); + connect(updater.get(), SIGNAL(updateAvailable()), SLOT(updateAvailable())); + // if automatic update checks are allowed, start one. + if(MMC->settings()->get("AutoUpdate").toBool()) + on_actionCheckUpdate_triggered(); + assets_downloader = new OneSixAssets(); connect(assets_downloader, SIGNAL(indexStarted()), SLOT(assetsIndexStarted())); connect(assets_downloader, SIGNAL(filesStarted()), SLOT(assetsFilesStarted())); @@ -417,6 +426,24 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *ev) return QMainWindow::eventFilter(obj, ev); } +void MainWindow::updateAvailable() +{ + UpdateDialog dlg; + UpdateAction action = (UpdateAction) dlg.exec(); + switch(action) + { + case UPDATE_LATER: + QLOG_INFO() << "Don't install update yet!"; + break; + case UPDATE_NOW: + QLOG_INFO() << "Install update NOW!"; + break; + case UPDATE_ONEXIT: + QLOG_INFO() << "Install update on exit!"; + break; + } +} + void MainWindow::onCatToggled(bool state) { setCatBackground(state); @@ -604,6 +631,8 @@ void MainWindow::on_actionConfig_Folder_triggered() void MainWindow::on_actionCheckUpdate_triggered() { + auto updater = MMC->goupdate(); + updater->checkForUpdate(); } void MainWindow::on_actionSettings_triggered() diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 59cfa3c9..e3713f89 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -161,6 +161,8 @@ slots: void startTask(Task *task); + void updateAvailable(); + void activeAccountChanged(); void changeActiveAccount(); diff --git a/gui/dialogs/UpdateDialog.cpp b/gui/dialogs/UpdateDialog.cpp new file mode 100644 index 00000000..c56798b4 --- /dev/null +++ b/gui/dialogs/UpdateDialog.cpp @@ -0,0 +1,28 @@ +#include "UpdateDialog.h" +#include "ui_UpdateDialog.h" +#include "gui/Platform.h" + +UpdateDialog::UpdateDialog(QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDialog) +{ + MultiMCPlatform::fixWM_CLASS(this); + ui->setupUi(this); +} + +UpdateDialog::~UpdateDialog() +{ +} + +void UpdateDialog::on_btnUpdateLater_clicked() +{ + reject(); +} + +void UpdateDialog::on_btnUpdateNow_clicked() +{ + done(UPDATE_NOW); +} + +void UpdateDialog::on_btnUpdateOnExit_clicked() +{ + done(UPDATE_ONEXIT); +} diff --git a/gui/dialogs/UpdateDialog.h b/gui/dialogs/UpdateDialog.h new file mode 100644 index 00000000..c13eb6bf --- /dev/null +++ b/gui/dialogs/UpdateDialog.h @@ -0,0 +1,46 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace Ui +{ +class UpdateDialog; +} + +enum UpdateAction +{ + UPDATE_LATER = QDialog::Rejected, + UPDATE_NOW = QDialog::Accepted, + UPDATE_ONEXIT = 2 +}; + +class UpdateDialog : public QDialog +{ + Q_OBJECT + +public: + explicit UpdateDialog(QWidget *parent = 0); + ~UpdateDialog(); + +private: + Ui::UpdateDialog *ui; +public slots: + void on_btnUpdateNow_clicked(); + void on_btnUpdateOnExit_clicked(); + void on_btnUpdateLater_clicked(); +}; diff --git a/gui/dialogs/UpdateDialog.ui b/gui/dialogs/UpdateDialog.ui new file mode 100644 index 00000000..f2361bd3 --- /dev/null +++ b/gui/dialogs/UpdateDialog.ui @@ -0,0 +1,63 @@ + + + UpdateDialog + + + + 0 + 0 + 350 + 260 + + + + MultiMC Update + + + + :/icons/toolbar/checkupdate:/icons/toolbar/checkupdate + + + + + + A new MultiMC update is available! + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Update now + + + + + + + + 0 + 0 + + + + Don't update yet + + + + + + + + + + diff --git a/logic/GoUpdate.cpp b/logic/GoUpdate.cpp new file mode 100644 index 00000000..6ac53d19 --- /dev/null +++ b/logic/GoUpdate.cpp @@ -0,0 +1,99 @@ + +#include "GoUpdate.h" + +#include "config.h" +#include "logger/QsLog.h" + +GoUpdate::GoUpdate() +{ + currentBuildIndex = VERSION_BUILD; + builderName = VERSION_BUILD_TYPE; + repoUrlBase = VERSION_REPO; +} + +void GoUpdate::updateCheckFailed() +{ + // TODO: log errors better + QLOG_ERROR() << "Update check failed for reasons unknown."; +} + +void GoUpdate::updateCheckFinished() +{ + QJsonParseError jsonError; + QByteArray data; + { + ByteArrayDownloadPtr dl = + std::dynamic_pointer_cast(index_job->first()); + data = dl->m_data; + index_job.reset(); + } + + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + if (jsonError.error != QJsonParseError::NoError || !jsonDoc.isObject()) + { + return; + } + + QVariant doc = jsonDoc.toVariant(); + auto stuff = doc.toMap(); + + // check api version (or later, branch?) + int ApiVersion = stuff["ApiVersion"].toInt(); + if (ApiVersion != 0) + return; + + // parse and store the channel list + auto parsedChannels = stuff["Channels"].toList(); + for (auto channel : parsedChannels) + { + auto chanMap = channel.toMap(); + channels.append({chanMap["Id"].toString(), chanMap["Name"].toString(), + chanMap["CurrentVersion"].toInt()}); + } + + // parse and store the version list + auto parsedVersions = stuff["Versions"].toList(); + for (auto version : parsedVersions) + { + auto verMap = version.toMap(); + int versionId = verMap["Id"].toInt(); + versions.append({versionId, verMap["Name"].toString()}); + if (currentBuildIndex < versionId) + { + newBuildIndex = versionId; + } + } + + if (newBuildIndex != -1) + { + QLOG_INFO() << "Update is available."; + emit updateAvailable(); + } + else + { + QLOG_INFO() << "Update check finished."; + } +} + +void GoUpdate::checkForUpdate() +{ + if (repoUrlBase == "invalid") + { + return; + } + + auto job = new NetJob("Assets index"); + job->addNetAction( + ByteArrayDownload::make(QUrl(repoUrlBase + "/" + VERSION_BRANCH + "/index.json"))); + connect(job, SIGNAL(succeeded()), SLOT(updateCheckFinished())); + connect(job, SIGNAL(failed()), SLOT(updateCheckFailed())); + index_job.reset(job); + job->start(); +} + +/* + files.multimc.org/lin64/ + Hi Forkkie + files.multimc.org/win32/ + files.multimc.org/lin32/ +*/ diff --git a/logic/GoUpdate.h b/logic/GoUpdate.h new file mode 100644 index 00000000..756a71cf --- /dev/null +++ b/logic/GoUpdate.h @@ -0,0 +1,43 @@ +#pragma once +#include "net/NetJob.h" + +class GoUpdate : public QObject +{ + Q_OBJECT + +public: + struct version_channel + { + QString id; + QString name; + int latestVersion; + }; + + struct version_summary + { + int id; + QString name; + }; + +signals: + void updateAvailable(); + +private slots: + void updateCheckFinished(); + void updateCheckFailed(); + +public: + GoUpdate(); + void checkForUpdate(); +private: + NetJobPtr index_job; + NetJobPtr fromto_job; + + QString repoUrlBase; + QString builderName; + int currentBuildIndex; + int newBuildIndex = -1; + + QList versions; + QList channels; +}; diff --git a/mmc_updater/CMakeLists.txt b/mmc_updater/CMakeLists.txt new file mode 100644 index 00000000..ef4b096d --- /dev/null +++ b/mmc_updater/CMakeLists.txt @@ -0,0 +1,44 @@ +project(updater) + +cmake_minimum_required(VERSION 2.6) +enable_testing() +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +include_directories(depends) + +if (WIN32) + include_directories(depends/win32cpp/include) + + if(MSVC) + # - Link the updater binary statically with the Visual C++ runtime + # so that the executable can function standalone. + # - Enable PDB generation for release builds + set(CMAKE_CXX_FLAGS_DEBUG "/MT") + set(CMAKE_C_FLAGS_DEBUG "/MT") + + set(CMAKE_CXX_FLAGS_RELEASE "/MT /Zi /O2 /Ob2 /D NDEBUG") + set(CMAKE_C_FLAGS_RELEASE "/MT /Zi /O2 /Ob2 /D NDEBUG") + remove_definitions(-DUNICODE -D_UNICODE) + endif() +else() + # optimize for reduced code size + set(CMAKE_CXX_FLAGS_RELEASE "-Os") + set(CMAKE_C_FLAGS_RELEASE "-Os") +endif() + +if (APPLE) + # Build the updater as a dual 32/64bit binary. If only one architecture + # is required, removing the other architecture will reduce the size + # of the updater binary + set(CMAKE_OSX_ARCHITECTURES i386;x86_64) + + # Build the updater so that it works on OS X 10.5 and above. + set(MIN_OSX_VERSION 10.5) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${MIN_OSX_VERSION}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${MIN_OSX_VERSION}") +endif() + +add_subdirectory(src) +add_subdirectory(depends/AnyOption) +add_subdirectory(depends/tinyxml) + diff --git a/mmc_updater/LICENSE b/mmc_updater/LICENSE new file mode 100644 index 00000000..f71a89be --- /dev/null +++ b/mmc_updater/LICENSE @@ -0,0 +1,19 @@ + +This project is licensed under a BSD license. + +The Mendeley Desktop icon graphics and name are trademarks of Mendeley Ltd. +and must be removed or replaced - see src/AppInfo.cpp and the files +in src/resources. + +=== + +Copyright (c) 2011, Mendeley Ltd. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mmc_updater/README.md b/mmc_updater/README.md new file mode 100644 index 00000000..fa3c41ae --- /dev/null +++ b/mmc_updater/README.md @@ -0,0 +1,138 @@ +This tool is a component of a cross-platform auto-update system. +It is responsible for performing the installation of an update after +the necessary files have been downloaded to a temporary directory. + +It was originally written for use with Mendeley Desktop (see www.mendeley.com) + +The tool consists of a single small binary which performs update installation, +an XML file format describing the contents of an update (an 'update script') +and a tool to create update scripts from a directory containing an installed application. + +To perform an update, the application (or another separate tool) needs to download +the updater binary, an update script and one or more compressed packages +containing the files for the update to a temporary directory. It then needs +to invoke the updater, specifying the location where the application is installed, +the location of the compressed packages and the path to the update script. + +Once the updater has been started, it: + + 1. Waits for the application to exit + 2. Acquires the necessary priviledges to install the updates, prompting + the user if necessary. + 3. Installs the updates, displaying progress to the user in a small dialog + 4. Performs cleanup and any additional actions required as part of the update + 5. Starts the new version of the main application. + + In the event of a failure during the update, the installation is rolled back + to its previous state and a message is presented to the user. + +## Building the Updater + + Create a new directory for the build and from that directory run: + + cmake + make + + The updater binary will be built in the src/ directory. + + You should also run the tests in src/tests to verify that the updater is + functioning correctly. + +## Preparing an Update + + 1. Create a directory containing your application's files, + laid out in the same way and with the same permissions as they would be when installed. + 2. Create a config file specifying how the application's files should be + partitioned into packages - see tools/config-template.json + 3. Use the tools/create-packages.rb script to create a file_list.xml file + and a set of package files required for updates. + 4. Upload the file_list.xml file and packages to a server + + After step 4 is done, you need to notify existing installs that an update + is available. The installed application then needs to download the + relevant packages, file_list.xml file and updater binary to a temporary + directory and invoke the updater. + + See doc/update-hosting for more details on hosting and delivering the updates. + +## Invoking the Updater + + Once the application has downloaded an update, it needs to invoke it. The syntax is: + + updater --install-dir --package-dir --script