aboutsummaryrefslogtreecommitdiff
path: root/launcher/InstanceList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/InstanceList.cpp')
-rw-r--r--launcher/InstanceList.cpp103
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;
}