From 0cb97d954d14b8703169a2b7208eea660c9691a8 Mon Sep 17 00:00:00 2001 From: Arttu Tarkiainen Date: Tue, 25 Feb 2020 16:03:54 +0200 Subject: Add command line option to disable checking of free space on target Also move functionality to PackageManagerCore::checkAvailableSpace() for more convenient later usage, if we want to use this without starting the Wizard GUI. Task-number: QTIFW-1602 Change-Id: I4f2d3cc78bc542475fe9c51b9364b1b221098e4a Reviewed-by: Katja Marttila --- src/libs/installer/packagemanagercore.cpp | 103 ++++++++++++++++++++++++++++ src/libs/installer/packagemanagercore.h | 3 + src/libs/installer/packagemanagercore_p.cpp | 2 + src/libs/installer/packagemanagercore_p.h | 1 + src/libs/installer/packagemanagergui.cpp | 93 ++----------------------- src/sdk/commandlineparser.cpp | 3 + src/sdk/constants.h | 1 + src/sdk/installerbase.cpp | 3 + 8 files changed, 120 insertions(+), 89 deletions(-) diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index 392dfb7b0..50671cebe 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -1942,6 +1942,109 @@ void PackageManagerCore::dropAdminRights() RemoteClient::instance().setActive(false); } +/*! + Sets checkAvailableSpace based on value of \c check. +*/ +void PackageManagerCore::setCheckAvailableSpace(bool check) +{ + d->m_checkAvailableSpace = check; +} + +/*! + Checks available disk space if the feature is not explicitly disabled. Informative + text about space status can be retrieved by passing \c message parameter. Returns + \a true if there is sufficient free space on installation and temporary volumes. +*/ +bool PackageManagerCore::checkAvailableSpace(QString &message) const +{ + const quint64 extraSpace = 256 * 1024 * 1024LL; + quint64 required(requiredDiskSpace()); + quint64 tempRequired(requiredTemporaryDiskSpace()); + if (required < extraSpace) { + required += 0.1 * required; + tempRequired += 0.1 * tempRequired; + } else { + required += extraSpace; + tempRequired += extraSpace; + } + + quint64 repositorySize = 0; + const bool createLocalRepository = createLocalRepositoryFromBinary(); + if (createLocalRepository && isInstaller()) { + repositorySize = QFile(QCoreApplication::applicationFilePath()).size(); + // if we create a local repository, take that space into account as well + required += repositorySize; + } + + qDebug() << "Installation space required:" << humanReadableSize(required) << "Temporary space " + "required:" << humanReadableSize(tempRequired) << "Local repository size:" + << humanReadableSize(repositorySize); + + if (d->m_checkAvailableSpace) { + const VolumeInfo tempVolume = VolumeInfo::fromPath(QDir::tempPath()); + const VolumeInfo targetVolume = VolumeInfo::fromPath(value(scTargetDir)); + + const quint64 tempVolumeAvailableSize = tempVolume.availableSize(); + const quint64 installVolumeAvailableSize = targetVolume.availableSize(); + + // at the moment there is no better way to check this + if (targetVolume.size() == 0 && installVolumeAvailableSize == 0) { + qDebug().nospace() << "Cannot determine available space on device. " + "Volume descriptor: " << targetVolume.volumeDescriptor() + << ", Mount path: " << targetVolume.mountPath() << ". Continue silently."; + return true; + } + + const bool tempOnSameVolume = (targetVolume == tempVolume); + if (tempOnSameVolume) { + qDebug() << "Tmp and install directories are on the same volume. Volume mount point:" + << targetVolume.mountPath() << "Free space available:" + << humanReadableSize(installVolumeAvailableSize); + } else { + qDebug() << "Tmp is on a different volume than the installation directory. Tmp volume mount point:" + << tempVolume.mountPath() << "Free space available:" + << humanReadableSize(tempVolumeAvailableSize) << "Install volume mount point:" + << targetVolume.mountPath() << "Free space available:" + << humanReadableSize(installVolumeAvailableSize); + } + + if (tempOnSameVolume && (installVolumeAvailableSize <= (required + tempRequired))) { + message = tr("Not enough disk space to store temporary files and the " + "installation. %1 are available, while %2 are at least required.").arg( + humanReadableSize(installVolumeAvailableSize), humanReadableSize(required + tempRequired)); + return false; + } + + if (installVolumeAvailableSize < required) { + message = tr("Not enough disk space to store all selected components! %1 are " + "available while %2 are at least required.").arg(humanReadableSize(installVolumeAvailableSize), + humanReadableSize(required)); + return false; + } + + if (tempVolumeAvailableSize < tempRequired) { + message = tr("Not enough disk space to store temporary files! %1 are available " + "while %2 are at least required.").arg(humanReadableSize(tempVolumeAvailableSize), + humanReadableSize(tempRequired)); + return false; + } + + if (installVolumeAvailableSize - required < 0.01 * targetVolume.size()) { + // warn for less than 1% of the volume's space being free + message = tr("The volume you selected for installation seems to have sufficient space for " + "installation, but there will be less than 1% of the volume's space available afterwards."); + } else if (installVolumeAvailableSize - required < 100 * 1024 * 1024LL) { + // warn for less than 100MB being free + message = tr("The volume you selected for installation seems to have sufficient " + "space for installation, but there will be less than 100 MB available afterwards."); + } + } + message = QString::fromLatin1("%1 %2").arg(message, tr("Installation will use %1 of disk space.") + .arg(humanReadableSize(requiredDiskSpace()))).simplified(); + + return true; +} + /*! Returns \c true if a process with \a name is running. On Windows, the comparison is case-insensitive. diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h index 0fe946caf..93c28e2d5 100644 --- a/src/libs/installer/packagemanagercore.h +++ b/src/libs/installer/packagemanagercore.h @@ -240,6 +240,9 @@ public: Q_INVOKABLE bool gainAdminRights(); Q_INVOKABLE void dropAdminRights(); + void setCheckAvailableSpace(bool check); + bool checkAvailableSpace(QString &message) const; + Q_INVOKABLE quint64 requiredDiskSpace() const; Q_INVOKABLE quint64 requiredTemporaryDiskSpace() const; diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 98b10af83..11e612d8b 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -216,6 +216,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core) , m_guiObject(nullptr) , m_remoteFileEngineHandler(nullptr) , m_foundEssentialUpdate(false) + , m_checkAvailableSpace(true) { } @@ -247,6 +248,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q , m_guiObject(nullptr) , m_remoteFileEngineHandler(new RemoteFileEngineHandler) , m_foundEssentialUpdate(false) + , m_checkAvailableSpace(true) { foreach (const OperationBlob &operation, performedOperations) { QScopedPointer op(KDUpdater::UpdateOperationFactory::instance() diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index 42b1879c7..311145f8a 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -184,6 +184,7 @@ public: bool m_needsHardRestart; bool m_testChecksum; bool m_launchedAsRoot; + bool m_checkAvailableSpace; bool m_completeUninstall; bool m_needToWriteMaintenanceTool; PackageManagerCoreData m_data; diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp index 0ccd53da2..88e788b02 100644 --- a/src/libs/installer/packagemanagergui.cpp +++ b/src/libs/installer/packagemanagergui.cpp @@ -2538,100 +2538,15 @@ void ReadyForInstallationPage::entering() m_taskDetailsBrowser->setVisible(!componentsOk || isVerbose()); setComplete(componentsOk); - const VolumeInfo tempVolume = VolumeInfo::fromPath(QDir::tempPath()); - const VolumeInfo targetVolume = VolumeInfo::fromPath(packageManagerCore()->value(scTargetDir)); - - const quint64 tempVolumeAvailableSize = tempVolume.availableSize(); - const quint64 installVolumeAvailableSize = targetVolume.availableSize(); - - // at the moment there is no better way to check this - if (targetVolume.size() == 0 && installVolumeAvailableSize == 0) { - qDebug().nospace() << "Cannot determine available space on device. " - "Volume descriptor: " << targetVolume.volumeDescriptor() - << ", Mount path: " << targetVolume.mountPath() << ". Continue silently."; - return; // TODO: Shouldn't this also disable the "Next" button? - } - - const bool tempOnSameVolume = (targetVolume == tempVolume); - if (tempOnSameVolume) { - qDebug() << "Tmp and install directories are on the same volume. Volume mount point:" - << targetVolume.mountPath() << "Free space available:" - << humanReadableSize(installVolumeAvailableSize); - } else { - qDebug() << "Tmp is on a different volume than the installation directory. Tmp volume mount point:" - << tempVolume.mountPath() << "Free space available:" - << humanReadableSize(tempVolumeAvailableSize) << "Install volume mount point:" - << targetVolume.mountPath() << "Free space available:" - << humanReadableSize(installVolumeAvailableSize); - } - - const quint64 extraSpace = 256 * 1024 * 1024LL; - quint64 required(packageManagerCore()->requiredDiskSpace()); - quint64 tempRequired(packageManagerCore()->requiredTemporaryDiskSpace()); - if (required < extraSpace) { - required += 0.1 * required; - tempRequired += 0.1 * tempRequired; + QString spaceInfo; + if (packageManagerCore()->checkAvailableSpace(spaceInfo)) { + m_msgLabel->setText(QString::fromLatin1("%1 %2").arg(m_msgLabel->text(), spaceInfo)); } else { - required += extraSpace; - tempRequired += extraSpace; - } - - quint64 repositorySize = 0; - const bool createLocalRepository = packageManagerCore()->createLocalRepositoryFromBinary(); - if (createLocalRepository && packageManagerCore()->isInstaller()) { - repositorySize = QFile(QCoreApplication::applicationFilePath()).size(); - // if we create a local repository, take that space into account as well - required += repositorySize; - } - - qDebug() << "Installation space required:" << humanReadableSize(required) << "Temporary space " - "required:" << humanReadableSize(tempRequired) << "Local repository size:" - << humanReadableSize(repositorySize); - - if (tempOnSameVolume && (installVolumeAvailableSize <= (required + tempRequired))) { - m_msgLabel->setText(tr("Not enough disk space to store temporary files and the " - "installation. %1 are available, while %2 are at least required.") - .arg(humanReadableSize(installVolumeAvailableSize), - humanReadableSize(required + tempRequired))); - setComplete(false); - return; - } - - if (installVolumeAvailableSize < required) { - m_msgLabel->setText(tr("Not enough disk space to store all selected components! %1 are available " - "while %2 are at least required.").arg(humanReadableSize(installVolumeAvailableSize), - humanReadableSize(required))); - setComplete(false); - return; - } - - if (tempVolumeAvailableSize < tempRequired) { - m_msgLabel->setText(tr("Not enough disk space to store temporary files! %1 are available " - "while %2 are at least required.").arg(humanReadableSize(tempVolumeAvailableSize), - humanReadableSize(tempRequired))); + m_msgLabel->setText(spaceInfo); setComplete(false); - return; - } - - if (installVolumeAvailableSize - required < 0.01 * targetVolume.size()) { - // warn for less than 1% of the volume's space being free - m_msgLabel->setText(tr("The volume you selected for installation seems to have sufficient " - "space for installation, but there will be less than 1% of the volume's space " - "available afterwards. %1").arg(m_msgLabel->text())); - } else if (installVolumeAvailableSize - required < 100 * 1024 * 1024LL) { - // warn for less than 100MB being free - m_msgLabel->setText(tr("The volume you selected for installation seems to have sufficient " - "space for installation, but there will be less than 100 MB available afterwards. %1") - .arg(m_msgLabel->text())); } - - m_msgLabel->setText(QString::fromLatin1("%1 %2").arg(m_msgLabel->text(), - tr("Installation will use %1 of disk space.") - .arg(humanReadableSize(packageManagerCore()->requiredDiskSpace())))); } - - /*! Called when end users leave the page and the PackageManagerGui:currentPageChanged() signal is triggered. diff --git a/src/sdk/commandlineparser.cpp b/src/sdk/commandlineparser.cpp index 3d0d2412a..e29ae2df7 100644 --- a/src/sdk/commandlineparser.cpp +++ b/src/sdk/commandlineparser.cpp @@ -71,6 +71,9 @@ CommandLineParser::CommandLineParser() m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::NoForceInstallation), QLatin1String("Allow deselecting components that are marked as forced."))); + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::NoSizeChecking), + QLatin1String("Disable checking of free space for installation target."))); + m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::ShowVirtualComponents), QLatin1String("Show virtual components in installer and package manager."))); diff --git a/src/sdk/constants.h b/src/sdk/constants.h index e9eca9103..a1f7b12cf 100644 --- a/src/sdk/constants.h +++ b/src/sdk/constants.h @@ -44,6 +44,7 @@ const char CheckUpdates[] = "checkupdates"; const char Updater[] = "updater"; const char ManagePackages[] = "manage-packages"; const char NoForceInstallation[] = "no-force-installations"; +const char NoSizeChecking[] = "no-size-checking"; const char ShowVirtualComponents[] = "show-virtual-components"; const char LoggingRules[] = "logging-rules"; const char CreateLocalRepository[] = "create-local-repository"; diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp index 247b4ab57..e6cf150ca 100644 --- a/src/sdk/installerbase.cpp +++ b/src/sdk/installerbase.cpp @@ -252,6 +252,9 @@ int InstallerBase::run() } m_core->setTemporaryRepositories(repoList, false, true); } + // Disable checking for free space on target + if (parser.isSet(QLatin1String(CommandLineOptions::NoSizeChecking))) + m_core->setCheckAvailableSpace(false); QInstaller::PackageManagerCore::setNoForceInstallation(parser .isSet(QLatin1String(CommandLineOptions::NoForceInstallation))); -- cgit v1.2.3