summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MultiMC.cpp69
-rw-r--r--MultiMC.h18
-rw-r--r--gui/MainWindow.cpp27
-rw-r--r--gui/MainWindow.h5
-rw-r--r--gui/dialogs/UpdateDialog.ui7
-rw-r--r--logic/updater/DownloadUpdateTask.cpp5
-rw-r--r--logic/updater/DownloadUpdateTask.h5
-rw-r--r--mmc_updater/src/UpdateInstaller.cpp2
8 files changed, 128 insertions, 10 deletions
diff --git a/MultiMC.cpp b/MultiMC.cpp
index 128e71f3..e3107ac4 100644
--- a/MultiMC.cpp
+++ b/MultiMC.cpp
@@ -2,10 +2,12 @@
#include "MultiMC.h"
#include <iostream>
#include <QDir>
+#include <QFileInfo>
#include <QNetworkAccessManager>
#include <QTranslator>
#include <QLibraryInfo>
#include <QMessageBox>
+#include <QStringList>
#include "gui/MainWindow.h"
#include "gui/dialogs/VersionSelectDialog.h"
@@ -409,6 +411,65 @@ std::shared_ptr<JavaVersionList> MultiMC::javalist()
return m_javalist;
}
+#ifdef WINDOWS
+#define UPDATER_BIN "updater.exe"
+#elif LINUX
+#define UPDATER_BIN "updater"
+#elif OSX
+#define UPDATER_BIN "updater"
+#else
+#error Unsupported operating system.
+#endif
+
+void MultiMC::installUpdates(const QString& updateFilesDir, bool restartOnFinish)
+{
+ QLOG_INFO() << "Installing updates.";
+#if LINUX
+ // On Linux, the MultiMC executable file is actually in the bin folder inside the installation directory.
+ // This means that MultiMC's *actual* install path is the parent folder.
+ // We need to tell the updater to run with this directory as the install path, rather than the bin folder where the executable is.
+ // On other operating systems, we'll just use the path to the executable.
+ QString appDir = QFileInfo(MMC->applicationDirPath()).dir().path();
+
+ // On Linux, we also need to set the finish command to the launch script, rather than the binary.
+ QString finishCmd = PathCombine(appDir, "MultiMC");
+#else
+ QString appDir = MMC->applicationDirPath();
+ QString finishCmd = MMC->applicationFilePath();
+#endif
+
+ // Build the command we'll use to run the updater.
+ // Note, the above comment about the app dir path on Linux is irrelevant here because the updater binary is always in the
+ // same folder as the main binary.
+ QString updaterBinary = PathCombine(MMC->applicationDirPath(), UPDATER_BIN);
+ QStringList args;
+ // ./updater --install-dir $INSTALL_DIR --package-dir $UPDATEFILES_DIR --script $UPDATEFILES_DIR/file_list.xml --wait $PID --mode main
+ args << "--install-dir" << appDir;
+ args << "--package-dir" << updateFilesDir;
+ args << "--script" << PathCombine(updateFilesDir, "file_list.xml");
+ args << "--wait" << QString::number(MMC->applicationPid());
+
+ if (restartOnFinish)
+ args << "--finish-cmd" << finishCmd;
+
+ QLOG_INFO() << "Running updater with command" << updaterBinary << args.join(" ");
+
+ QProcess::startDetached(updaterBinary, args);
+
+ // Now that we've started the updater, quit MultiMC.
+ MMC->quit();
+}
+
+void MultiMC::setUpdateOnExit(const QString& updateFilesDir)
+{
+ m_updateOnExitPath = updateFilesDir;
+}
+
+QString MultiMC::getExitUpdatePath() const
+{
+ return m_updateOnExitPath;
+}
+
int main_gui(MultiMC &app)
{
// show main window
@@ -417,7 +478,13 @@ int main_gui(MultiMC &app)
mainWin.restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("MainWindowGeometry").toByteArray()));
mainWin.show();
mainWin.checkSetDefaultJava();
- return app.exec();
+ auto exitCode = app.exec();
+
+ // Update if necessary.
+ if (!app.getExitUpdatePath().isEmpty())
+ app.installUpdates(app.getExitUpdatePath(), false);
+
+ return exitCode;
}
int main(int argc, char *argv[])
diff --git a/MultiMC.h b/MultiMC.h
index 659104ba..22cea029 100644
--- a/MultiMC.h
+++ b/MultiMC.h
@@ -98,6 +98,22 @@ public:
std::shared_ptr<JavaVersionList> javalist();
+ /*!
+ * Installs update from the given update files directory.
+ */
+ void installUpdates(const QString& updateFilesDir, bool restartOnFinish=false);
+
+ /*!
+ * Sets MultiMC to install updates from the given directory when it exits.
+ */
+ void setUpdateOnExit(const QString& updateFilesDir);
+
+ /*!
+ * Gets the path to install updates from on exit.
+ * If this is an empty string, no updates should be installed on exit.
+ */
+ QString getExitUpdatePath() const;
+
private:
void initLogger();
@@ -124,6 +140,8 @@ private:
QsLogging::DestinationPtr m_fileDestination;
QsLogging::DestinationPtr m_debugDestination;
+ QString m_updateOnExitPath;
+
Status m_status = MultiMC::Failed;
MultiMCVersion m_version;
};
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index 618884ef..7ea5c291 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -439,20 +439,31 @@ void MainWindow::updateAvailable(QString repo, QString versionName, int versionI
QLOG_INFO() << "Update will be installed later.";
break;
case UPDATE_NOW:
- {
- QLOG_INFO() << "Installing update.";
- ProgressDialog updateDlg(this);
- DownloadUpdateTask updateTask(repo, versionId, &updateDlg);
- updateDlg.exec(&updateTask);
- }
+ downloadUpdates(repo, versionId);
break;
case UPDATE_ONEXIT:
- // TODO: Implement installing updates on exit.
- QLOG_INFO() << "Installing on exit is not implemented yet.";
+ downloadUpdates(repo, versionId, true);
break;
}
}
+void MainWindow::downloadUpdates(QString repo, int versionId, bool installOnExit)
+{
+ QLOG_INFO() << "Downloading updates.";
+ // TODO: If the user chooses to update on exit, we should download updates in the background.
+ // Doing so is a bit complicated, because we'd have to make sure it finished downloading before actually exiting MultiMC.
+ ProgressDialog updateDlg(this);
+ DownloadUpdateTask updateTask(repo, versionId, &updateDlg);
+ // If the task succeeds, install the updates.
+ if (updateDlg.exec(&updateTask))
+ {
+ if (installOnExit)
+ MMC->setUpdateOnExit(updateTask.updateFilesDir());
+ else
+ MMC->installUpdates(updateTask.updateFilesDir());
+ }
+}
+
void MainWindow::onCatToggled(bool state)
{
setCatBackground(state);
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index 1f498eca..b99c54ee 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -168,6 +168,11 @@ slots:
void changeActiveAccount();
void repopulateAccountsMenu();
+
+ /*!
+ * Runs the DownloadUpdateTask and installs updates.
+ */
+ void downloadUpdates(QString repo, int versionId, bool installOnExit=false);
protected:
bool eventFilter(QObject *obj, QEvent *ev);
diff --git a/gui/dialogs/UpdateDialog.ui b/gui/dialogs/UpdateDialog.ui
index f2361bd3..1fe65e62 100644
--- a/gui/dialogs/UpdateDialog.ui
+++ b/gui/dialogs/UpdateDialog.ui
@@ -42,6 +42,13 @@
</widget>
</item>
<item>
+ <widget class="QPushButton" name="btnUpdateOnExit">
+ <property name="text">
+ <string>Update after MultiMC closes</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QPushButton" name="btnUpdateLater">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
diff --git a/logic/updater/DownloadUpdateTask.cpp b/logic/updater/DownloadUpdateTask.cpp
index 7c5eb84a..ef975c93 100644
--- a/logic/updater/DownloadUpdateTask.cpp
+++ b/logic/updater/DownloadUpdateTask.cpp
@@ -391,3 +391,8 @@ void DownloadUpdateTask::fileDownloadProgressChanged(qint64 current, qint64 tota
setProgress((int)(((float)current / (float)total)*100));
}
+QString DownloadUpdateTask::updateFilesDir()
+{
+ return m_updateFilesDir.path();
+}
+
diff --git a/logic/updater/DownloadUpdateTask.h b/logic/updater/DownloadUpdateTask.h
index dc30ca15..f5b23d12 100644
--- a/logic/updater/DownloadUpdateTask.h
+++ b/logic/updater/DownloadUpdateTask.h
@@ -28,6 +28,11 @@ class DownloadUpdateTask : public Task
public:
explicit DownloadUpdateTask(QString repoUrl, int versionId, QObject* parent=0);
+
+ /*!
+ * Gets the directory that contains the update files.
+ */
+ QString updateFilesDir();
protected:
// TODO: We should probably put these data structures into a separate header...
diff --git a/mmc_updater/src/UpdateInstaller.cpp b/mmc_updater/src/UpdateInstaller.cpp
index 3ddc1ec0..ced6ff39 100644
--- a/mmc_updater/src/UpdateInstaller.cpp
+++ b/mmc_updater/src/UpdateInstaller.cpp
@@ -388,7 +388,7 @@ void UpdateInstaller::restartMainApp()
{
try
{
- std::string command = m_installDir + '/' + m_finishCmd;
+ std::string command = m_finishCmd;
std::list<std::string> args;
if (!command.empty())