diff options
Diffstat (limited to 'launcher/InstanceList.cpp')
-rw-r--r-- | launcher/InstanceList.cpp | 103 |
1 files changed, 72 insertions, 31 deletions
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 4447a17c..cebd70d7 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -535,7 +535,20 @@ InstancePtr InstanceList::getInstanceById(QString instId) const return InstancePtr(); } -QModelIndex InstanceList::getInstanceIndexById(const QString& id) const +InstancePtr InstanceList::getInstanceByManagedName(const QString& managed_name) const +{ + if (managed_name.isEmpty()) + return {}; + + for (auto instance : m_instances) { + if (instance->getManagedPackName() == managed_name) + return instance; + } + + return {}; +} + +QModelIndex InstanceList::getInstanceIndexById(const QString &id) const { return index(getInstIndex(getInstanceById(id).get())); } @@ -764,21 +777,17 @@ class InstanceStaging : public Task { Q_OBJECT const unsigned minBackoff = 1; const unsigned maxBackoff = 16; - public: - InstanceStaging(InstanceList* parent, Task* child, const QString& stagingPath, const QString& instanceName, const QString& groupName) - : backoff(minBackoff, maxBackoff) + InstanceStaging(InstanceList* parent, InstanceTask* child, QString stagingPath, InstanceName const& instanceName, QString groupName) + : m_parent(parent), backoff(minBackoff, maxBackoff), m_stagingPath(std::move(stagingPath)), m_instance_name(std::move(instanceName)), m_groupName(std::move(groupName)) { - m_parent = parent; m_child.reset(child); connect(child, &Task::succeeded, this, &InstanceStaging::childSucceded); connect(child, &Task::failed, this, &InstanceStaging::childFailed); + connect(child, &Task::aborted, this, &InstanceStaging::childAborted); + connect(child, &Task::abortStatusChanged, this, &InstanceStaging::setAbortable); connect(child, &Task::status, this, &InstanceStaging::setStatus); connect(child, &Task::progress, this, &InstanceStaging::setProgress); - m_instanceName = instanceName; - m_groupName = groupName; - m_stagingPath = stagingPath; - m_backoffTimer.setSingleShot(true); connect(&m_backoffTimer, &QTimer::timeout, this, &InstanceStaging::childSucceded); } @@ -787,17 +796,16 @@ class InstanceStaging : public Task { // FIXME/TODO: add ability to abort during instance commit retries bool abort() override { - if (m_child && m_child->canAbort()) { - return m_child->abort(); - } - return false; + if (!canAbort()) + return false; + + m_child->abort(); + + return Task::abort(); } bool canAbort() const override { - if (m_child && m_child->canAbort()) { - return true; - } - return false; + return (m_child && m_child->canAbort()); } protected: @@ -808,7 +816,8 @@ class InstanceStaging : public Task { void childSucceded() { unsigned sleepTime = backoff(); - if (m_parent->commitStagedInstance(m_stagingPath, m_instanceName, m_groupName)) { + if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, m_child->shouldOverride())) + { emitSucceeded(); return; } @@ -817,7 +826,7 @@ class InstanceStaging : public Task { emitFailed(tr("Failed to commit instance, even after multiple retries. It is being blocked by something.")); return; } - qDebug() << "Failed to commit instance" << m_instanceName << "Initiating backoff:" << sleepTime; + qDebug() << "Failed to commit instance" << m_instance_name.name() << "Initiating backoff:" << sleepTime; m_backoffTimer.start(sleepTime * 500); } void childFailed(const QString& reason) @@ -826,7 +835,13 @@ class InstanceStaging : public Task { emitFailed(reason); } - private: + void childAborted() + { + emitAborted(); + } + +private: + InstanceList * m_parent; /* * WHY: the whole reason why this uses an exponential backoff retry scheme is antivirus on Windows. * Basically, it starts messing things up while the launcher is extracting/creating instances @@ -834,9 +849,8 @@ class InstanceStaging : public Task { */ ExponentialSeries backoff; QString m_stagingPath; - InstanceList* m_parent; - unique_qobject_ptr<Task> m_child; - QString m_instanceName; + unique_qobject_ptr<InstanceTask> m_child; + InstanceName m_instance_name; QString m_groupName; QTimer m_backoffTimer; }; @@ -846,7 +860,7 @@ Task* InstanceList::wrapInstanceTask(InstanceTask* task) auto stagingPath = getStagedInstancePath(); task->setStagingPath(stagingPath); task->setParentSettings(m_globalSettings); - return new InstanceStaging(this, task, stagingPath, task->name(), task->group()); + return new InstanceStaging(this, task, stagingPath, *task, task->group()); } QString InstanceList::getStagedInstancePath() @@ -866,23 +880,50 @@ QString InstanceList::getStagedInstancePath() return path; } -bool InstanceList::commitStagedInstance(const QString& path, const QString& instanceName, const QString& groupName) +bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, bool should_override) { QDir dir; - QString instID = FS::DirNameFromString(instanceName, m_instDir); + QString instID; + InstancePtr inst; + + if (should_override) { + // This is to avoid problems when the instance folder gets manually renamed + if ((inst = getInstanceByManagedName(instanceName.originalName()))) { + instID = QFileInfo(inst->instanceRoot()).fileName(); + } else if ((inst = getInstanceByManagedName(instanceName.modifiedName()))) { + instID = QFileInfo(inst->instanceRoot()).fileName(); + } else { + instID = FS::RemoveInvalidFilenameChars(instanceName.modifiedName(), '-'); + } + } else { + instID = FS::DirNameFromString(instanceName.modifiedName(), m_instDir); + } + { WatchLock lock(m_watcher, m_instDir); QString destination = FS::PathCombine(m_instDir, instID); - if (!dir.rename(path, destination)) { - qWarning() << "Failed to move" << path << "to" << destination; - return false; + + if (should_override) { + if (!FS::overrideFolder(destination, path)) { + qWarning() << "Failed to override" << path << "to" << destination; + return false; + } + } else { + if (!dir.rename(path, destination)) { + qWarning() << "Failed to move" << path << "to" << destination; + return false; + } + + m_instanceGroupIndex[instID] = groupName; + m_groupNameCache.insert(groupName); } - m_instanceGroupIndex[instID] = groupName; + instanceSet.insert(instID); - m_groupNameCache.insert(groupName); + emit instancesChanged(); emit instanceSelectRequest(instID); } + saveGroupList(); return true; } |