diff options
| author | Mikaël Capelle <capelle.mikael@gmail.com> | 2020-05-30 15:00:10 +0200 |
|---|---|---|
| committer | Mikaël Capelle <capelle.mikael@gmail.com> | 2020-05-30 15:00:10 +0200 |
| commit | 3f768ae53a580dbb41e8940bbf8b79336ead309c (patch) | |
| tree | b513ada02270c96daec09ce2f3d3a90c7eb0b775 /src/installationmanager.cpp | |
| parent | 21296a64594729a59360131270beaadf61cbced0 (diff) | |
Implement createFile() for the installation manager.
Diffstat (limited to 'src/installationmanager.cpp')
| -rw-r--r-- | src/installationmanager.cpp | 91 |
1 files changed, 88 insertions, 3 deletions
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index 62a97591..b5efc5f6 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -207,6 +207,60 @@ QStringList InstallationManager::extractFiles(std::vector<std::shared_ptr<const } +QString InstallationManager::createFile(std::shared_ptr<const MOBase::FileTreeEntry> entry) +{ + // Use QTemporaryFile to create the temporary file with the given template: + QTemporaryFile tempFile(QDir::cleanPath(QDir::tempPath() + QDir::separator() + "mo2-install")); + + // Turn-off autoRemove otherwise the file is deleted when destructor is called: + tempFile.setAutoRemove(false); + + // Open/Close the file so that installer can use it properly: + if (!tempFile.open()) { + return QString(); + } + tempFile.close(); + + // fileName() returns the full path since we provide a full path in the constructor: + const QString absPath = tempFile.fileName(); + + m_CreatedFiles[entry] = absPath; + m_TempFilesToDelete.insert(QDir::temp().relativeFilePath(absPath)); + + // Returns the path with native separators: + return QDir::toNativeSeparators(absPath); +} + +void InstallationManager::cleanCreatedFiles(std::shared_ptr<const MOBase::IFileTree> fileTree) +{ + // We simply have to check if all the entries have fileTree as a parent: + for (auto it = std::begin(m_CreatedFiles); it != std::end(m_CreatedFiles); ) { + + // Find the parent - Could this be in FileTreeEntry? + bool found = false; + { + auto parent = it->first->parent(); + while (parent && !found) { + if (parent == fileTree) { + found = true; + } + else { + parent = parent->parent(); + } + } + } + + // If the parent was not found, we remove the entry, otherwize we move to the next one: + if (!found) { + it = m_CreatedFiles.erase(it); + } + else { + ++it; + } + } +} + + IPluginInstaller::EInstallResult InstallationManager::installArchive(GuessedValue<QString> &modName, const QString &archiveName, int modId) { // in earlier versions the modName was copied here and the copy passed to install. I don't know why I did this and it causes @@ -368,6 +422,7 @@ IPluginInstaller::EInstallResult InstallationManager::doInstall(GuessedValue<QSt log::debug("installing to \"{}\"", targetDirectoryNative); + // Extract the archive: m_InstallationProgress = new QProgressDialog(m_ParentWidget); ON_BLOCK_EXIT([this] () { m_InstallationProgress->cancel(); @@ -410,6 +465,24 @@ IPluginInstaller::EInstallResult InstallationManager::doInstall(GuessedValue<QSt } } + // Copy the created files: + for (auto& p : m_CreatedFiles) { + QString destPath = QDir::cleanPath(targetDirectory + QDir::separator() + p.first->path()); + log::debug("Moving {} to {}.", p.second, destPath); + + // We need to remove the path if it exists: + if (QFile::exists(destPath)) { + QFile::remove(destPath); + } + + QDir dir = QFileInfo(destPath).absoluteDir(); + if (!dir.exists()) { + dir.mkpath("."); + } + + QFile::copy(p.second, destPath); + } + QSettings settingsFile(targetDirectory + "/meta.ini", QSettings::IniFormat); // overwrite settings only if they are actually are available or haven't been set before @@ -467,6 +540,10 @@ bool InstallationManager::isRunning() void InstallationManager::postInstallCleanup() { + // Clear the list of created files: + m_CreatedFiles.clear(); + + // Close the archive: m_ArchiveHandler->close(); // directories we may want to remove. sorted from longest to shortest to ensure we remove subdirectories first. @@ -618,15 +695,23 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil = installerSimple->install(modName, filesTree, version, modID); if (installResult == IPluginInstaller::RESULT_SUCCESS) { - // Note: Have to maintain a pointer to IFileTree because install() takes a - // reference. This could be an issue if ever a plugin creates a new tree that - // is not a ArchiveFileTree. + // Downcast to an actual ArchiveFileTree and map to the archive. Test if + // the tree is still an ArchiveFileTree, otherwize it means the installer + // did some bad stuff. ArchiveFileTree* p = dynamic_cast<ArchiveFileTree*>(filesTree.get()); if (p == nullptr) { throw IncompatibilityException(tr("Invalid file tree returned by plugin.")); } + + // Detach the file tree (this ensure the parent is null and call to path() + // stops at this root): + p->detach(); + p->mapToArchive(m_ArchiveHandler); + // Clean the created files: + cleanCreatedFiles(filesTree); + // the simple installer only prepares the installation, the rest // works the same for all installers installResult = doInstall(modName, gameName, modID, version, newestVersion, categoryID, fileCategoryID, repository); |
