mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2025-05-29 21:30:18 +02:00
Merge pull request #1409 from Trial97/import_zip
feat: refactored Instance ImportTask
This commit is contained in:
commit
e961cab352
@ -395,20 +395,15 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
{
|
{
|
||||||
static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "-%0.log";
|
static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "-%0.log";
|
||||||
static const QString logBase = FS::PathCombine("logs", baseLogFile);
|
static const QString logBase = FS::PathCombine("logs", baseLogFile);
|
||||||
auto moveFile = [](const QString& oldName, const QString& newName) {
|
|
||||||
QFile::remove(newName);
|
|
||||||
QFile::copy(oldName, newName);
|
|
||||||
QFile::remove(oldName);
|
|
||||||
};
|
|
||||||
if (FS::ensureFolderPathExists("logs")) { // if this did not fail
|
if (FS::ensureFolderPathExists("logs")) { // if this did not fail
|
||||||
for (auto i = 0; i <= 4; i++)
|
for (auto i = 0; i <= 4; i++)
|
||||||
if (auto oldName = baseLogFile.arg(i);
|
if (auto oldName = baseLogFile.arg(i);
|
||||||
QFile::exists(oldName)) // do not pointlessly delete new files if the old ones are not there
|
QFile::exists(oldName)) // do not pointlessly delete new files if the old ones are not there
|
||||||
moveFile(oldName, logBase.arg(i));
|
FS::move(oldName, logBase.arg(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = 4; i > 0; i--)
|
for (auto i = 4; i > 0; i--)
|
||||||
moveFile(logBase.arg(i - 1), logBase.arg(i));
|
FS::move(logBase.arg(i - 1), logBase.arg(i));
|
||||||
|
|
||||||
logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
|
logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
|
||||||
if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
#include "BaseInstaller.h"
|
#include "BaseInstaller.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
|
||||||
BaseInstaller::BaseInstaller() {}
|
BaseInstaller::BaseInstaller() {}
|
||||||
@ -42,7 +43,7 @@ bool BaseInstaller::add(MinecraftInstance* to)
|
|||||||
|
|
||||||
bool BaseInstaller::remove(MinecraftInstance* from)
|
bool BaseInstaller::remove(MinecraftInstance* from)
|
||||||
{
|
{
|
||||||
return QFile::remove(filename(from->instanceRoot()));
|
return FS::deletePath(filename(from->instanceRoot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstaller::filename(const QString& root) const
|
QString BaseInstaller::filename(const QString& root) const
|
||||||
|
@ -647,6 +647,19 @@ void ExternalLinkFileProcess::runLinkFile()
|
|||||||
qDebug() << "Process exited";
|
qDebug() << "Process exited";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool moveByCopy(const QString& source, const QString& dest)
|
||||||
|
{
|
||||||
|
if (!copy(source, dest)()) { // copy
|
||||||
|
qDebug() << "Copy of" << source << "to" << dest << "failed!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!deletePath(source)) { // remove original
|
||||||
|
qDebug() << "Deletion of" << source << "failed!";
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool move(const QString& source, const QString& dest)
|
bool move(const QString& source, const QString& dest)
|
||||||
{
|
{
|
||||||
std::error_code err;
|
std::error_code err;
|
||||||
@ -654,13 +667,14 @@ bool move(const QString& source, const QString& dest)
|
|||||||
ensureFilePathExists(dest);
|
ensureFilePathExists(dest);
|
||||||
fs::rename(StringUtils::toStdString(source), StringUtils::toStdString(dest), err);
|
fs::rename(StringUtils::toStdString(source), StringUtils::toStdString(dest), err);
|
||||||
|
|
||||||
if (err) {
|
if (err.value() != 0) {
|
||||||
qWarning() << "Failed to move file:" << QString::fromStdString(err.message());
|
if (moveByCopy(source, dest))
|
||||||
qDebug() << "Source file:" << source;
|
return true;
|
||||||
qDebug() << "Destination file:" << dest;
|
qDebug() << "Move of" << source << "to" << dest << "failed!";
|
||||||
|
qWarning() << "Failed to move file:" << QString::fromStdString(err.message()) << QString::number(err.value());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return err.value() == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool deletePath(QString path)
|
bool deletePath(QString path)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
void InstanceCreationTask::executeTask()
|
void InstanceCreationTask::executeTask()
|
||||||
{
|
{
|
||||||
@ -45,7 +46,7 @@ void InstanceCreationTask::executeTask()
|
|||||||
if (!QFile::exists(path))
|
if (!QFile::exists(path))
|
||||||
continue;
|
continue;
|
||||||
qDebug() << "Removing" << path;
|
qDebug() << "Removing" << path;
|
||||||
if (!QFile::remove(path)) {
|
if (!FS::deletePath(path)) {
|
||||||
qCritical() << "Couldn't remove the old conflicting files.";
|
qCritical() << "Couldn't remove the old conflicting files.";
|
||||||
emitFailed(tr("Failed to remove old conflicting files."));
|
emitFailed(tr("Failed to remove old conflicting files."));
|
||||||
return;
|
return;
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <quazip/quazipdir.h>
|
#include <quazip/quazipdir.h>
|
||||||
|
|
||||||
@ -68,15 +69,8 @@ bool InstanceImportTask::abort()
|
|||||||
if (!canAbort())
|
if (!canAbort())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_filesNetJob)
|
if (task)
|
||||||
m_filesNetJob->abort();
|
task->abort();
|
||||||
if (m_extractFuture.isRunning()) {
|
|
||||||
// NOTE: The tasks created by QtConcurrent::run() can't actually get cancelled,
|
|
||||||
// but we can use this call to check the state when the extraction finishes.
|
|
||||||
m_extractFuture.cancel();
|
|
||||||
m_extractFuture.waitForFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task::abort();
|
return Task::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +83,6 @@ void InstanceImportTask::executeTask()
|
|||||||
processZipPack();
|
processZipPack();
|
||||||
} else {
|
} else {
|
||||||
setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString()));
|
setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString()));
|
||||||
m_downloadRequired = true;
|
|
||||||
|
|
||||||
downloadFromUrl();
|
downloadFromUrl();
|
||||||
}
|
}
|
||||||
@ -97,115 +90,132 @@ void InstanceImportTask::executeTask()
|
|||||||
|
|
||||||
void InstanceImportTask::downloadFromUrl()
|
void InstanceImportTask::downloadFromUrl()
|
||||||
{
|
{
|
||||||
const QString path = m_sourceUrl.host() + '/' + m_sourceUrl.path();
|
const QString path(m_sourceUrl.host() + '/' + m_sourceUrl.path());
|
||||||
|
|
||||||
auto entry = APPLICATION->metacache()->resolveEntry("general", path);
|
auto entry = APPLICATION->metacache()->resolveEntry("general", path);
|
||||||
entry->setStale(true);
|
entry->setStale(true);
|
||||||
m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network()));
|
|
||||||
m_filesNetJob->addNetAction(Net::ApiDownload::makeCached(m_sourceUrl, entry));
|
|
||||||
m_archivePath = entry->getFullPath();
|
m_archivePath = entry->getFullPath();
|
||||||
|
|
||||||
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded);
|
auto filesNetJob = makeShared<NetJob>(tr("Modpack download"), APPLICATION->network());
|
||||||
connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged);
|
filesNetJob->addNetAction(Net::ApiDownload::makeCached(m_sourceUrl, entry));
|
||||||
connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propagateStepProgress);
|
|
||||||
connect(m_filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::downloadFailed);
|
connect(filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::processZipPack);
|
||||||
connect(m_filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::downloadAborted);
|
connect(filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::setProgress);
|
||||||
m_filesNetJob->start();
|
connect(filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propagateStepProgress);
|
||||||
|
connect(filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::emitFailed);
|
||||||
|
connect(filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::emitAborted);
|
||||||
|
task.reset(filesNetJob);
|
||||||
|
filesNetJob->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceImportTask::downloadSucceeded()
|
QString InstanceImportTask::getRootFromZip(QuaZip* zip, const QString& root)
|
||||||
{
|
{
|
||||||
processZipPack();
|
if (!isRunning()) {
|
||||||
m_filesNetJob.reset();
|
return {};
|
||||||
}
|
}
|
||||||
|
QuaZipDir rootDir(zip, root);
|
||||||
|
for (auto&& fileName : rootDir.entryList(QDir::Files)) {
|
||||||
|
setDetails(fileName);
|
||||||
|
if (fileName == "instance.cfg") {
|
||||||
|
qDebug() << "MultiMC:" << true;
|
||||||
|
m_modpackType = ModpackType::MultiMC;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
if (fileName == "manifest.json") {
|
||||||
|
qDebug() << "Flame:" << true;
|
||||||
|
m_modpackType = ModpackType::Flame;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
void InstanceImportTask::downloadFailed(QString reason)
|
QCoreApplication::processEvents();
|
||||||
{
|
}
|
||||||
emitFailed(reason);
|
|
||||||
m_filesNetJob.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceImportTask::downloadProgressChanged(qint64 current, qint64 total)
|
// Recurse the search to non-ignored subfolders
|
||||||
{
|
for (auto&& fileName : rootDir.entryList(QDir::Dirs)) {
|
||||||
setProgress(current, total);
|
if ("overrides/" == fileName)
|
||||||
}
|
continue;
|
||||||
|
|
||||||
void InstanceImportTask::downloadAborted()
|
QString result = getRootFromZip(zip, root + fileName);
|
||||||
{
|
if (!result.isEmpty())
|
||||||
emitAborted();
|
return result;
|
||||||
m_filesNetJob.reset();
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceImportTask::processZipPack()
|
void InstanceImportTask::processZipPack()
|
||||||
{
|
{
|
||||||
setStatus(tr("Extracting modpack"));
|
setStatus(tr("Attempting to determine instance type"));
|
||||||
QDir extractDir(m_stagingPath);
|
QDir extractDir(m_stagingPath);
|
||||||
qDebug() << "Attempting to create instance from" << m_archivePath;
|
qDebug() << "Attempting to create instance from" << m_archivePath;
|
||||||
|
|
||||||
// open the zip and find relevant files in it
|
// open the zip and find relevant files in it
|
||||||
m_packZip.reset(new QuaZip(m_archivePath));
|
auto packZip = std::make_shared<QuaZip>(m_archivePath);
|
||||||
if (!m_packZip->open(QuaZip::mdUnzip)) {
|
if (!packZip->open(QuaZip::mdUnzip)) {
|
||||||
emitFailed(tr("Unable to open supplied modpack zip file."));
|
emitFailed(tr("Unable to open supplied modpack zip file."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QuaZipDir packZipDir(m_packZip.get());
|
QuaZipDir packZipDir(packZip.get());
|
||||||
|
qDebug() << "Attempting to determine instance type";
|
||||||
|
|
||||||
// https://docs.modrinth.com/docs/modpacks/format_definition/#storage
|
|
||||||
bool modrinthFound = packZipDir.exists("/modrinth.index.json");
|
|
||||||
bool technicFound = packZipDir.exists("/bin/modpack.jar") || packZipDir.exists("/bin/version.json");
|
|
||||||
QString root;
|
QString root;
|
||||||
|
|
||||||
// NOTE: Prioritize modpack platforms that aren't searched for recursively.
|
// NOTE: Prioritize modpack platforms that aren't searched for recursively.
|
||||||
// Especially Flame has a very common filename for its manifest, which may appear inside overrides for example
|
// Especially Flame has a very common filename for its manifest, which may appear inside overrides for example
|
||||||
if (modrinthFound) {
|
// https://docs.modrinth.com/docs/modpacks/format_definition/#storage
|
||||||
|
if (packZipDir.exists("/modrinth.index.json")) {
|
||||||
// process as Modrinth pack
|
// process as Modrinth pack
|
||||||
qDebug() << "Modrinth:" << modrinthFound;
|
qDebug() << "Modrinth:" << true;
|
||||||
m_modpackType = ModpackType::Modrinth;
|
m_modpackType = ModpackType::Modrinth;
|
||||||
} else if (technicFound) {
|
} else if (packZipDir.exists("/bin/modpack.jar") || packZipDir.exists("/bin/version.json")) {
|
||||||
// process as Technic pack
|
// process as Technic pack
|
||||||
qDebug() << "Technic:" << technicFound;
|
qDebug() << "Technic:" << true;
|
||||||
extractDir.mkpath("minecraft");
|
extractDir.mkpath("minecraft");
|
||||||
extractDir.cd("minecraft");
|
extractDir.cd("minecraft");
|
||||||
m_modpackType = ModpackType::Technic;
|
m_modpackType = ModpackType::Technic;
|
||||||
} else {
|
} else {
|
||||||
QStringList paths_to_ignore{ "overrides/" };
|
root = getRootFromZip(packZip.get());
|
||||||
|
setDetails("");
|
||||||
if (QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg", paths_to_ignore); !mmcRoot.isNull()) {
|
|
||||||
// process as MultiMC instance/pack
|
|
||||||
qDebug() << "MultiMC:" << mmcRoot;
|
|
||||||
root = mmcRoot;
|
|
||||||
m_modpackType = ModpackType::MultiMC;
|
|
||||||
} else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore);
|
|
||||||
!flameRoot.isNull()) {
|
|
||||||
// process as Flame pack
|
|
||||||
qDebug() << "Flame:" << flameRoot;
|
|
||||||
root = flameRoot;
|
|
||||||
m_modpackType = ModpackType::Flame;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (m_modpackType == ModpackType::Unknown) {
|
if (m_modpackType == ModpackType::Unknown) {
|
||||||
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setStatus(tr("Extracting modpack"));
|
||||||
|
|
||||||
// make sure we extract just the pack
|
// make sure we extract just the pack
|
||||||
m_extractFuture =
|
auto zipTask = makeShared<MMCZip::ExtractZipTask>(packZip, extractDir, root);
|
||||||
QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath());
|
|
||||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished);
|
auto progressStep = std::make_shared<TaskStepProgress>();
|
||||||
m_extractFutureWatcher.setFuture(m_extractFuture);
|
connect(zipTask.get(), &Task::finished, this, [this, progressStep] {
|
||||||
|
progressStep->state = TaskStepState::Succeeded;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(zipTask.get(), &Task::succeeded, this, &InstanceImportTask::extractFinished);
|
||||||
|
connect(zipTask.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
|
||||||
|
connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) {
|
||||||
|
progressStep->state = TaskStepState::Failed;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
emitFailed(reason);
|
||||||
|
});
|
||||||
|
connect(zipTask.get(), &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress);
|
||||||
|
|
||||||
|
connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) {
|
||||||
|
progressStep->update(current, total);
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) {
|
||||||
|
progressStep->status = status;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
task.reset(zipTask);
|
||||||
|
zipTask->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceImportTask::extractFinished()
|
void InstanceImportTask::extractFinished()
|
||||||
{
|
{
|
||||||
m_packZip.reset();
|
|
||||||
|
|
||||||
if (m_extractFuture.isCanceled())
|
|
||||||
return;
|
|
||||||
if (!m_extractFuture.result().has_value()) {
|
|
||||||
emitFailed(tr("Failed to extract modpack"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir extractDir(m_stagingPath);
|
QDir extractDir(m_stagingPath);
|
||||||
|
|
||||||
qDebug() << "Fixing permissions for extracted pack files...";
|
qDebug() << "Fixing permissions for extracted pack files...";
|
||||||
@ -324,13 +334,15 @@ void InstanceImportTask::processMultiMC()
|
|||||||
m_instIcon = instance.iconKey();
|
m_instIcon = instance.iconKey();
|
||||||
|
|
||||||
auto importIconPath = IconUtils::findBestIconIn(instance.instanceRoot(), m_instIcon);
|
auto importIconPath = IconUtils::findBestIconIn(instance.instanceRoot(), m_instIcon);
|
||||||
|
if (importIconPath.isNull() || !QFile::exists(importIconPath))
|
||||||
|
importIconPath = IconUtils::findBestIconIn(instance.instanceRoot(), "icon.png");
|
||||||
if (!importIconPath.isNull() && QFile::exists(importIconPath)) {
|
if (!importIconPath.isNull() && QFile::exists(importIconPath)) {
|
||||||
// import icon
|
// import icon
|
||||||
auto iconList = APPLICATION->icons();
|
auto iconList = APPLICATION->icons();
|
||||||
if (iconList->iconFileExists(m_instIcon)) {
|
if (iconList->iconFileExists(m_instIcon)) {
|
||||||
iconList->deleteIcon(m_instIcon);
|
iconList->deleteIcon(m_instIcon);
|
||||||
}
|
}
|
||||||
iconList->installIcons({ importIconPath });
|
iconList->installIcon(importIconPath, m_instIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
|
@ -39,11 +39,8 @@
|
|||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include "InstanceTask.h"
|
#include "InstanceTask.h"
|
||||||
#include "QObjectPtr.h"
|
|
||||||
#include "modplatform/flame/PackManifest.h"
|
|
||||||
#include "net/NetJob.h"
|
|
||||||
#include "settings/SettingsObject.h"
|
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
class QuaZip;
|
class QuaZip;
|
||||||
@ -54,35 +51,26 @@ class InstanceImportTask : public InstanceTask {
|
|||||||
explicit InstanceImportTask(const QUrl& sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {});
|
explicit InstanceImportTask(const QUrl& sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {});
|
||||||
|
|
||||||
bool abort() override;
|
bool abort() override;
|
||||||
const QVector<Flame::File>& getBlockedFiles() const { return m_blockedMods; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Entry point for tasks.
|
//! Entry point for tasks.
|
||||||
virtual void executeTask() override;
|
virtual void executeTask() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processZipPack();
|
|
||||||
void processMultiMC();
|
void processMultiMC();
|
||||||
void processTechnic();
|
void processTechnic();
|
||||||
void processFlame();
|
void processFlame();
|
||||||
void processModrinth();
|
void processModrinth();
|
||||||
|
QString getRootFromZip(QuaZip* zip, const QString& root = "");
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void downloadSucceeded();
|
void processZipPack();
|
||||||
void downloadFailed(QString reason);
|
|
||||||
void downloadProgressChanged(qint64 current, qint64 total);
|
|
||||||
void downloadAborted();
|
|
||||||
void extractFinished();
|
void extractFinished();
|
||||||
|
|
||||||
private: /* data */
|
private: /* data */
|
||||||
NetJob::Ptr m_filesNetJob;
|
|
||||||
QUrl m_sourceUrl;
|
QUrl m_sourceUrl;
|
||||||
QString m_archivePath;
|
QString m_archivePath;
|
||||||
bool m_downloadRequired = false;
|
Task::Ptr task;
|
||||||
std::unique_ptr<QuaZip> m_packZip;
|
|
||||||
QFuture<std::optional<QStringList>> m_extractFuture;
|
|
||||||
QFutureWatcher<std::optional<QStringList>> m_extractFutureWatcher;
|
|
||||||
QVector<Flame::File> m_blockedMods;
|
|
||||||
enum class ModpackType {
|
enum class ModpackType {
|
||||||
Unknown,
|
Unknown,
|
||||||
MultiMC,
|
MultiMC,
|
||||||
|
@ -972,7 +972,6 @@ bool InstanceList::commitStagedInstance(const QString& path,
|
|||||||
if (groupName.isEmpty() && !groupName.isNull())
|
if (groupName.isEmpty() && !groupName.isNull())
|
||||||
groupName = QString();
|
groupName = QString();
|
||||||
|
|
||||||
QDir dir;
|
|
||||||
QString instID;
|
QString instID;
|
||||||
InstancePtr inst;
|
InstancePtr inst;
|
||||||
|
|
||||||
@ -996,7 +995,7 @@ bool InstanceList::commitStagedInstance(const QString& path,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!dir.rename(path, destination)) {
|
if (!FS::move(path, destination)) {
|
||||||
qWarning() << "Failed to move" << path << "to" << destination;
|
qWarning() << "Failed to move" << path << "to" << destination;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#if defined(LAUNCHER_APPLICATION)
|
#if defined(LAUNCHER_APPLICATION)
|
||||||
@ -122,7 +123,7 @@ bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files,
|
|||||||
zip.setUtf8Enabled(true);
|
zip.setUtf8Enabled(true);
|
||||||
QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
|
QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
|
||||||
if (!zip.open(QuaZip::mdCreate)) {
|
if (!zip.open(QuaZip::mdCreate)) {
|
||||||
QFile::remove(fileCompressed);
|
FS::deletePath(fileCompressed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +131,7 @@ bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files,
|
|||||||
|
|
||||||
zip.close();
|
zip.close();
|
||||||
if (zip.getZipError() != 0) {
|
if (zip.getZipError() != 0) {
|
||||||
QFile::remove(fileCompressed);
|
FS::deletePath(fileCompressed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +145,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
QuaZip zipOut(targetJarPath);
|
QuaZip zipOut(targetJarPath);
|
||||||
zipOut.setUtf8Enabled(true);
|
zipOut.setUtf8Enabled(true);
|
||||||
if (!zipOut.open(QuaZip::mdCreate)) {
|
if (!zipOut.open(QuaZip::mdCreate)) {
|
||||||
QFile::remove(targetJarPath);
|
FS::deletePath(targetJarPath);
|
||||||
qCritical() << "Failed to open the minecraft.jar for modding";
|
qCritical() << "Failed to open the minecraft.jar for modding";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -162,7 +163,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
if (mod->type() == ResourceType::ZIPFILE) {
|
if (mod->type() == ResourceType::ZIPFILE) {
|
||||||
if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) {
|
if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) {
|
||||||
zipOut.close();
|
zipOut.close();
|
||||||
QFile::remove(targetJarPath);
|
FS::deletePath(targetJarPath);
|
||||||
qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
|
qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -171,7 +172,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
auto filename = mod->fileinfo();
|
auto filename = mod->fileinfo();
|
||||||
if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName())) {
|
if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName())) {
|
||||||
zipOut.close();
|
zipOut.close();
|
||||||
QFile::remove(targetJarPath);
|
FS::deletePath(targetJarPath);
|
||||||
qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
|
qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -194,7 +195,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
|
|
||||||
if (!compressDirFiles(&zipOut, parent_dir, files)) {
|
if (!compressDirFiles(&zipOut, parent_dir, files)) {
|
||||||
zipOut.close();
|
zipOut.close();
|
||||||
QFile::remove(targetJarPath);
|
FS::deletePath(targetJarPath);
|
||||||
qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
|
qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -202,7 +203,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
} else {
|
} else {
|
||||||
// Make sure we do not continue launching when something is missing or undefined...
|
// Make sure we do not continue launching when something is missing or undefined...
|
||||||
zipOut.close();
|
zipOut.close();
|
||||||
QFile::remove(targetJarPath);
|
FS::deletePath(targetJarPath);
|
||||||
qCritical() << "Failed to add unknown mod type" << mod->fileinfo().fileName() << "to the jar.";
|
qCritical() << "Failed to add unknown mod type" << mod->fileinfo().fileName() << "to the jar.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -210,7 +211,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
|
|
||||||
if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, [](const QString key) { return !key.contains("META-INF"); })) {
|
if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, [](const QString key) { return !key.contains("META-INF"); })) {
|
||||||
zipOut.close();
|
zipOut.close();
|
||||||
QFile::remove(targetJarPath);
|
FS::deletePath(targetJarPath);
|
||||||
qCritical() << "Failed to insert minecraft.jar contents.";
|
qCritical() << "Failed to insert minecraft.jar contents.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -218,7 +219,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
// Recompress the jar
|
// Recompress the jar
|
||||||
zipOut.close();
|
zipOut.close();
|
||||||
if (zipOut.getZipError() != 0) {
|
if (zipOut.getZipError() != 0) {
|
||||||
QFile::remove(targetJarPath);
|
FS::deletePath(targetJarPath);
|
||||||
qCritical() << "Failed to finalize minecraft.jar!";
|
qCritical() << "Failed to finalize minecraft.jar!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -332,9 +333,20 @@ std::optional<QStringList> extractSubDir(QuaZip* zip, const QString& subdir, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
extracted.append(target_file_path);
|
extracted.append(target_file_path);
|
||||||
QFile::setPermissions(target_file_path,
|
auto fileInfo = QFileInfo(target_file_path);
|
||||||
QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser);
|
if (fileInfo.isFile()) {
|
||||||
|
auto permissions = fileInfo.permissions();
|
||||||
|
auto maxPermisions = QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser |
|
||||||
|
QFileDevice::Permission::ReadGroup | QFileDevice::Permission::ReadOther;
|
||||||
|
auto minPermisions = QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
|
||||||
|
|
||||||
|
auto newPermisions = (permissions & maxPermisions) | minPermisions;
|
||||||
|
if (newPermisions != permissions) {
|
||||||
|
if (!QFile::setPermissions(target_file_path, newPermisions)) {
|
||||||
|
qWarning() << (QObject::tr("Could not fix permissions for %1").arg(target_file_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path;
|
qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path;
|
||||||
} while (zip->goToNextFile());
|
} while (zip->goToNextFile());
|
||||||
|
|
||||||
@ -492,10 +504,10 @@ auto ExportToZipTask::exportZip() -> ZipResult
|
|||||||
void ExportToZipTask::finish()
|
void ExportToZipTask::finish()
|
||||||
{
|
{
|
||||||
if (m_build_zip_future.isCanceled()) {
|
if (m_build_zip_future.isCanceled()) {
|
||||||
QFile::remove(m_output_path);
|
FS::deletePath(m_output_path);
|
||||||
emitAborted();
|
emitAborted();
|
||||||
} else if (auto result = m_build_zip_future.result(); result.has_value()) {
|
} else if (auto result = m_build_zip_future.result(); result.has_value()) {
|
||||||
QFile::remove(m_output_path);
|
FS::deletePath(m_output_path);
|
||||||
emitFailed(result.value());
|
emitFailed(result.value());
|
||||||
} else {
|
} else {
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
@ -512,6 +524,123 @@ bool ExportToZipTask::abort()
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
void ExtractZipTask::executeTask()
|
||||||
|
{
|
||||||
|
m_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); });
|
||||||
|
connect(&m_zip_watcher, &QFutureWatcher<ZipResult>::finished, this, &ExtractZipTask::finish);
|
||||||
|
m_zip_watcher.setFuture(m_zip_future);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ExtractZipTask::extractZip() -> ZipResult
|
||||||
|
{
|
||||||
|
auto target = m_output_dir.absolutePath();
|
||||||
|
auto target_top_dir = QUrl::fromLocalFile(target);
|
||||||
|
|
||||||
|
QStringList extracted;
|
||||||
|
|
||||||
|
qDebug() << "Extracting subdir" << m_subdirectory << "from" << m_input->getZipName() << "to" << target;
|
||||||
|
auto numEntries = m_input->getEntriesCount();
|
||||||
|
if (numEntries < 0) {
|
||||||
|
return ZipResult(tr("Failed to enumerate files in archive"));
|
||||||
|
}
|
||||||
|
if (numEntries == 0) {
|
||||||
|
logWarning(tr("Extracting empty archives seems odd..."));
|
||||||
|
return ZipResult();
|
||||||
|
}
|
||||||
|
if (!m_input->goToFirstFile()) {
|
||||||
|
return ZipResult(tr("Failed to seek to first file in zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus("Extracting files...");
|
||||||
|
setProgress(0, numEntries);
|
||||||
|
do {
|
||||||
|
if (m_zip_future.isCanceled())
|
||||||
|
return ZipResult();
|
||||||
|
setProgress(m_progress + 1, m_progressTotal);
|
||||||
|
QString file_name = m_input->getCurrentFileName();
|
||||||
|
if (!file_name.startsWith(m_subdirectory))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto relative_file_name = QDir::fromNativeSeparators(file_name.remove(0, m_subdirectory.size()));
|
||||||
|
auto original_name = relative_file_name;
|
||||||
|
setStatus("Unziping: " + relative_file_name);
|
||||||
|
|
||||||
|
// Fix subdirs/files ending with a / getting transformed into absolute paths
|
||||||
|
if (relative_file_name.startsWith('/'))
|
||||||
|
relative_file_name = relative_file_name.mid(1);
|
||||||
|
|
||||||
|
// Fix weird "folders with a single file get squashed" thing
|
||||||
|
QString sub_path;
|
||||||
|
if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) {
|
||||||
|
sub_path = relative_file_name.section('/', 0, -2) + '/';
|
||||||
|
FS::ensureFolderPathExists(FS::PathCombine(target, sub_path));
|
||||||
|
|
||||||
|
relative_file_name = relative_file_name.split('/').last();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString target_file_path;
|
||||||
|
if (relative_file_name.isEmpty()) {
|
||||||
|
target_file_path = target + '/';
|
||||||
|
} else {
|
||||||
|
target_file_path = FS::PathCombine(target_top_dir.toLocalFile(), sub_path, relative_file_name);
|
||||||
|
if (relative_file_name.endsWith('/') && !target_file_path.endsWith('/'))
|
||||||
|
target_file_path += '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) {
|
||||||
|
return ZipResult(tr("Extracting %1 was cancelled, because it was effectively outside of the target path %2")
|
||||||
|
.arg(relative_file_name, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JlCompress::extractFile(m_input.get(), "", target_file_path)) {
|
||||||
|
JlCompress::removeFile(extracted);
|
||||||
|
return ZipResult(tr("Failed to extract file %1 to %2").arg(original_name, target_file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
extracted.append(target_file_path);
|
||||||
|
auto fileInfo = QFileInfo(target_file_path);
|
||||||
|
if (fileInfo.isFile()) {
|
||||||
|
auto permissions = fileInfo.permissions();
|
||||||
|
auto maxPermisions = QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser |
|
||||||
|
QFileDevice::Permission::ReadGroup | QFileDevice::Permission::ReadOther;
|
||||||
|
auto minPermisions = QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
|
||||||
|
|
||||||
|
auto newPermisions = (permissions & maxPermisions) | minPermisions;
|
||||||
|
if (newPermisions != permissions) {
|
||||||
|
if (!QFile::setPermissions(target_file_path, newPermisions)) {
|
||||||
|
logWarning(tr("Could not fix permissions for %1").arg(target_file_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path;
|
||||||
|
} while (m_input->goToNextFile());
|
||||||
|
|
||||||
|
return ZipResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtractZipTask::finish()
|
||||||
|
{
|
||||||
|
if (m_zip_future.isCanceled()) {
|
||||||
|
emitAborted();
|
||||||
|
} else if (auto result = m_zip_future.result(); result.has_value()) {
|
||||||
|
emitFailed(result.value());
|
||||||
|
} else {
|
||||||
|
emitSucceeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtractZipTask::abort()
|
||||||
|
{
|
||||||
|
if (m_zip_future.isRunning()) {
|
||||||
|
m_zip_future.cancel();
|
||||||
|
// NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur
|
||||||
|
// immediately.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
} // namespace MMCZip
|
} // namespace MMCZip
|
||||||
|
@ -205,5 +205,30 @@ class ExportToZipTask : public Task {
|
|||||||
QFuture<ZipResult> m_build_zip_future;
|
QFuture<ZipResult> m_build_zip_future;
|
||||||
QFutureWatcher<ZipResult> m_build_zip_watcher;
|
QFutureWatcher<ZipResult> m_build_zip_watcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ExtractZipTask : public Task {
|
||||||
|
public:
|
||||||
|
ExtractZipTask(std::shared_ptr<QuaZip> input, QDir outputDir, QString subdirectory = "")
|
||||||
|
: m_input(input), m_output_dir(outputDir), m_subdirectory(subdirectory)
|
||||||
|
{}
|
||||||
|
virtual ~ExtractZipTask() = default;
|
||||||
|
|
||||||
|
typedef std::optional<QString> ZipResult;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void executeTask() override;
|
||||||
|
bool abort() override;
|
||||||
|
|
||||||
|
ZipResult extractZip();
|
||||||
|
void finish();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<QuaZip> m_input;
|
||||||
|
QDir m_output_dir;
|
||||||
|
QString m_subdirectory;
|
||||||
|
|
||||||
|
QFuture<ZipResult> m_zip_future;
|
||||||
|
QFutureWatcher<ZipResult> m_zip_watcher;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
} // namespace MMCZip
|
} // namespace MMCZip
|
||||||
|
@ -322,7 +322,7 @@ const MMCIcon* IconList::icon(const QString& key) const
|
|||||||
|
|
||||||
bool IconList::deleteIcon(const QString& key)
|
bool IconList::deleteIcon(const QString& key)
|
||||||
{
|
{
|
||||||
return iconFileExists(key) && QFile::remove(icon(key)->getFilePath());
|
return iconFileExists(key) && FS::deletePath(icon(key)->getFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IconList::trashIcon(const QString& key)
|
bool IconList::trashIcon(const QString& key)
|
||||||
|
@ -52,8 +52,7 @@ QString findBestIconIn(const QString& folder, const QString& iconKey)
|
|||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
it.next();
|
it.next();
|
||||||
auto fileInfo = it.fileInfo();
|
auto fileInfo = it.fileInfo();
|
||||||
|
if ((fileInfo.completeBaseName() == iconKey || fileInfo.fileName() == iconKey) && isIconSuffix(fileInfo.suffix()))
|
||||||
if (fileInfo.completeBaseName() == iconKey && isIconSuffix(fileInfo.suffix()))
|
|
||||||
return fileInfo.absoluteFilePath();
|
return fileInfo.absoluteFilePath();
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "BaseEntity.h"
|
#include "BaseEntity.h"
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include "net/ApiDownload.h"
|
#include "net/ApiDownload.h"
|
||||||
#include "net/HttpMetaCache.h"
|
#include "net/HttpMetaCache.h"
|
||||||
@ -83,8 +84,7 @@ bool Meta::BaseEntity::loadLocalFile()
|
|||||||
} catch (const Exception& e) {
|
} catch (const Exception& e) {
|
||||||
qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause());
|
qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause());
|
||||||
// just make sure it's gone and we never consider it again.
|
// just make sure it's gone and we never consider it again.
|
||||||
QFile::remove(fname);
|
return !FS::deletePath(fname);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ bool Component::revert()
|
|||||||
bool result = true;
|
bool result = true;
|
||||||
// just kill the file and reload
|
// just kill the file and reload
|
||||||
if (QFile::exists(filename)) {
|
if (QFile::exists(filename)) {
|
||||||
result = QFile::remove(filename);
|
result = FS::deletePath(filename);
|
||||||
}
|
}
|
||||||
if (result) {
|
if (result) {
|
||||||
// file gone...
|
// file gone...
|
||||||
|
@ -839,7 +839,7 @@ bool PackProfile::installCustomJar_internal(QString filepath)
|
|||||||
|
|
||||||
QFileInfo jarInfo(finalPath);
|
QFileInfo jarInfo(finalPath);
|
||||||
if (jarInfo.exists()) {
|
if (jarInfo.exists()) {
|
||||||
if (!QFile::remove(finalPath)) {
|
if (!FS::deletePath(finalPath)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ bool ResourceFolderModel::installResource(QString original_path)
|
|||||||
case ResourceType::ZIPFILE:
|
case ResourceType::ZIPFILE:
|
||||||
case ResourceType::LITEMOD: {
|
case ResourceType::LITEMOD: {
|
||||||
if (QFile::exists(new_path) || QFile::exists(new_path + QString(".disabled"))) {
|
if (QFile::exists(new_path) || QFile::exists(new_path + QString(".disabled"))) {
|
||||||
if (!QFile::remove(new_path)) {
|
if (!FS::deletePath(new_path)) {
|
||||||
qCritical() << "Cleaning up new location (" << new_path << ") was unsuccessful!";
|
qCritical() << "Cleaning up new location (" << new_path << ") was unsuccessful!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ void PackInstallTask::deleteExistingFiles()
|
|||||||
|
|
||||||
// Delete the files
|
// Delete the files
|
||||||
for (const auto& item : filesToDelete) {
|
for (const auto& item : filesToDelete) {
|
||||||
QFile::remove(item);
|
FS::deletePath(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -987,7 +987,7 @@ bool PackInstallTask::extractMods(const QMap<QString, VersionMod>& toExtract,
|
|||||||
// the copy from the Configs.zip
|
// the copy from the Configs.zip
|
||||||
QFileInfo fileInfo(to);
|
QFileInfo fileInfo(to);
|
||||||
if (fileInfo.exists()) {
|
if (fileInfo.exists()) {
|
||||||
if (!QFile::remove(to)) {
|
if (!FS::deletePath(to)) {
|
||||||
qWarning() << "Failed to delete" << to;
|
qWarning() << "Failed to delete" << to;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +322,7 @@ bool FlameCreationTask::createInstance()
|
|||||||
// Keep index file in case we need it some other time (like when changing versions)
|
// Keep index file in case we need it some other time (like when changing versions)
|
||||||
QString new_index_place(FS::PathCombine(parent_folder, "manifest.json"));
|
QString new_index_place(FS::PathCombine(parent_folder, "manifest.json"));
|
||||||
FS::ensureFilePathExists(new_index_place);
|
FS::ensureFilePathExists(new_index_place);
|
||||||
QFile::rename(index_path, new_index_place);
|
FS::move(index_path, new_index_place);
|
||||||
|
|
||||||
} catch (const JSONValidationError& e) {
|
} catch (const JSONValidationError& e) {
|
||||||
setError(tr("Could not understand pack manifest:\n") + e.cause());
|
setError(tr("Could not understand pack manifest:\n") + e.cause());
|
||||||
@ -336,7 +336,7 @@ bool FlameCreationTask::createInstance()
|
|||||||
Override::createOverrides("overrides", parent_folder, overridePath);
|
Override::createOverrides("overrides", parent_folder, overridePath);
|
||||||
|
|
||||||
QString mcPath = FS::PathCombine(m_stagingPath, "minecraft");
|
QString mcPath = FS::PathCombine(m_stagingPath, "minecraft");
|
||||||
if (!QFile::rename(overridePath, mcPath)) {
|
if (!FS::move(overridePath, mcPath)) {
|
||||||
setError(tr("Could not rename the overrides folder:\n") + m_pack.overrides);
|
setError(tr("Could not rename the overrides folder:\n") + m_pack.overrides);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ void createOverrides(const QString& name, const QString& parent_folder, const QS
|
|||||||
{
|
{
|
||||||
QString file_path(FS::PathCombine(parent_folder, name + ".txt"));
|
QString file_path(FS::PathCombine(parent_folder, name + ".txt"));
|
||||||
if (QFile::exists(file_path))
|
if (QFile::exists(file_path))
|
||||||
QFile::remove(file_path);
|
FS::deletePath(file_path);
|
||||||
|
|
||||||
FS::ensureFilePathExists(file_path);
|
FS::ensureFilePathExists(file_path);
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ void PackInstallTask::install()
|
|||||||
QDir unzipMcDir(m_stagingPath + "/unzip/minecraft");
|
QDir unzipMcDir(m_stagingPath + "/unzip/minecraft");
|
||||||
if (unzipMcDir.exists()) {
|
if (unzipMcDir.exists()) {
|
||||||
// ok, found minecraft dir, move contents to instance dir
|
// ok, found minecraft dir, move contents to instance dir
|
||||||
if (!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/minecraft")) {
|
if (!FS::move(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/minecraft")) {
|
||||||
emitFailed(tr("Failed to move unzipped Minecraft!"));
|
emitFailed(tr("Failed to move unzipped Minecraft!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ bool ModrinthCreationTask::createInstance()
|
|||||||
// Keep index file in case we need it some other time (like when changing versions)
|
// Keep index file in case we need it some other time (like when changing versions)
|
||||||
QString new_index_place(FS::PathCombine(parent_folder, "modrinth.index.json"));
|
QString new_index_place(FS::PathCombine(parent_folder, "modrinth.index.json"));
|
||||||
FS::ensureFilePathExists(new_index_place);
|
FS::ensureFilePathExists(new_index_place);
|
||||||
QFile::rename(index_path, new_index_place);
|
FS::move(index_path, new_index_place);
|
||||||
|
|
||||||
auto mcPath = FS::PathCombine(m_stagingPath, m_root_path);
|
auto mcPath = FS::PathCombine(m_stagingPath, m_root_path);
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ bool ModrinthCreationTask::createInstance()
|
|||||||
Override::createOverrides("overrides", parent_folder, override_path);
|
Override::createOverrides("overrides", parent_folder, override_path);
|
||||||
|
|
||||||
// Apply the overrides
|
// Apply the overrides
|
||||||
if (!QFile::rename(override_path, mcPath)) {
|
if (!FS::move(override_path, mcPath)) {
|
||||||
setError(tr("Could not rename the overrides folder:\n") + "overrides");
|
setError(tr("Could not rename the overrides folder:\n") + "overrides");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "ui_ImportPage.h"
|
#include "ui_ImportPage.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QMimeDatabase>
|
||||||
#include <QValidator>
|
#include <QValidator>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -51,6 +52,7 @@
|
|||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
|
|
||||||
#include "InstanceImportTask.h"
|
#include "InstanceImportTask.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
|
||||||
class UrlValidator : public QValidator {
|
class UrlValidator : public QValidator {
|
||||||
public:
|
public:
|
||||||
|
@ -352,15 +352,10 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
FS::ensureFolderPathExists(FS::PathCombine(m_dataPath, "logs"));
|
FS::ensureFolderPathExists(FS::PathCombine(m_dataPath, "logs"));
|
||||||
static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log";
|
static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log";
|
||||||
static const QString logBase = FS::PathCombine(m_dataPath, "logs", baseLogFile);
|
static const QString logBase = FS::PathCombine(m_dataPath, "logs", baseLogFile);
|
||||||
auto moveFile = [](const QString& oldName, const QString& newName) {
|
|
||||||
QFile::remove(newName);
|
|
||||||
QFile::copy(oldName, newName);
|
|
||||||
QFile::remove(oldName);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (FS::ensureFolderPathExists("logs")) { // enough history to track both launches of the updater during a portable install
|
if (FS::ensureFolderPathExists("logs")) { // enough history to track both launches of the updater during a portable install
|
||||||
moveFile(logBase.arg(1), logBase.arg(2));
|
FS::move(logBase.arg(1), logBase.arg(2));
|
||||||
moveFile(logBase.arg(0), logBase.arg(1));
|
FS::move(logBase.arg(0), logBase.arg(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
|
logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
|
||||||
@ -924,7 +919,7 @@ bool PrismUpdaterApp::callAppImageUpdate()
|
|||||||
|
|
||||||
void PrismUpdaterApp::clearUpdateLog()
|
void PrismUpdaterApp::clearUpdateLog()
|
||||||
{
|
{
|
||||||
QFile::remove(m_updateLogPath);
|
FS::deletePath(m_updateLogPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrismUpdaterApp::logUpdate(const QString& msg)
|
void PrismUpdaterApp::logUpdate(const QString& msg)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user