diff options
Diffstat (limited to 'src/sdk/main.cpp')
-rw-r--r-- | src/sdk/main.cpp | 87 |
1 files changed, 82 insertions, 5 deletions
diff --git a/src/sdk/main.cpp b/src/sdk/main.cpp index a2eb22189..abfc9dc5a 100644 --- a/src/sdk/main.cpp +++ b/src/sdk/main.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -38,13 +38,23 @@ #include <utils.h> #include <loggingutils.h> +#ifdef IFW_LIB7Z +#include <7zVersion.h> +#endif +#ifdef IFW_LIBARCHIVE +#include <archive.h> +#endif + #include <QCommandLineParser> #include <QDateTime> #include <QNetworkProxyFactory> +#include <QThread> +#include <QThreadPool> +#include <QDeadlineTimer> #include <iostream> -#if defined(Q_OS_MACOS) or defined(Q_OS_UNIX) +#if defined(Q_OS_MACOS) || defined(Q_OS_UNIX) # include <unistd.h> # include <sys/types.h> #endif @@ -56,8 +66,47 @@ #define SHA "Installer Framework SHA1: " QUOTE(_GIT_SHA1_) static const char PLACEHOLDER[32] = "MY_InstallerCreateDateTime_MY"; +#ifdef Q_OS_WIN +static void cleanupUpdate(const CommandLineParser &parser, bool *exit) +{ + QString cleanupPath; + QString cleanupOption; + *exit = false; + + if (parser.isSet(CommandLineOptions::scCleanupUpdate)) { + cleanupPath = parser.value(CommandLineOptions::scCleanupUpdate); + cleanupOption = CommandLineOptions::scCleanupUpdate; + } else if (parser.isSet(CommandLineOptions::scCleanupUpdateOnly)) { + cleanupPath = parser.value(CommandLineOptions::scCleanupUpdateOnly); + cleanupOption = CommandLineOptions::scCleanupUpdateOnly; + *exit = true; + } + + if (cleanupOption.isEmpty()) + return; + + // Since Windows does not support that the maintenance tool deletes itself we + // remove the old executable here after update (as the new maintenance tool). + if (!cleanupPath.isEmpty()) { + QFile fileToRemove(cleanupPath); + // Give up after 120 seconds if the old process has not exited and released the file + QDeadlineTimer deadline(120000); + while (fileToRemove.exists() && !deadline.hasExpired()) { + if (fileToRemove.remove()) { + std::cout << "Removed leftover file: " << qPrintable(cleanupPath) + << " after update." << std::endl; + } + QThread::msleep(1000); + } + } else { + std::cout << "Invalid value for option " << qPrintable(cleanupOption); + } +} +#endif + int main(int argc, char *argv[]) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (!qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { @@ -66,6 +115,7 @@ int main(int argc, char *argv[]) #if defined(Q_OS_WIN) QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); #endif +#endif // increase maximum numbers of file descriptors #if defined(Q_OS_MACOS) QCoreApplication::setSetuidAllowed(true); @@ -75,6 +125,13 @@ int main(int argc, char *argv[]) setrlimit(RLIMIT_NOFILE, &rl); #endif + // Try to avoid running into situations where the application would hang due to "nested" blocking + // usage of the global threadpool that has only one thread available, i.e. main thread invokes + // QtConcurrent::run(&myFunction) and myFunction() calls QtConcurrent::blockingFiltered() + // for a container. + if (QThread::idealThreadCount() == 1) + QThreadPool::globalInstance()->setMaxThreadCount(2); + // We need to start either a command line application or a GUI application. Since we // fail doing so at least on Linux while parsing the argument using a core application // object and later starting the GUI application, we now parse the arguments first. @@ -112,8 +169,10 @@ int main(int argc, char *argv[]) .arg(mutually.join(QLatin1String(", "))); sanityCheck = false; } - const QSet<QString> commands = parser.positionalArguments().toSet() - .intersect(CommandLineOptions::scCommandLineInterfaceOptions.toSet()); + const QStringList positionalArgs = parser.positionalArguments(); + QSet<QString> commands(positionalArgs.begin(), positionalArgs.end()); + commands.intersect(QSet<QString>(CommandLineOptions::scCommandLineInterfaceOptions.begin(), + CommandLineOptions::scCommandLineInterfaceOptions.end())); // Check sanity of the given argument sequence. if (commands.size() > 1) { sanityMessage = QString::fromLatin1("%1 commands provided, only one can be used at a time.") @@ -130,6 +189,12 @@ int main(int argc, char *argv[]) if (parser.isSet(CommandLineOptions::scVersionLong)) { std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl; +#ifdef IFW_LIB7Z + std::cout << "LZMA SDK version: " << MY_VERSION << std::endl; +#endif +#ifdef IFW_LIBARCHIVE + std::cout << "Libarchive version: " << archive_version_details() << std::endl; +#endif const QDateTime dateTime = QDateTime::fromString(QLatin1String(PLACEHOLDER), QLatin1String("yyyy-MM-dd - HH:mm:ss")); if (dateTime.isValid()) @@ -144,9 +209,18 @@ int main(int argc, char *argv[]) return help ? EXIT_SUCCESS : EXIT_FAILURE; } +#ifdef Q_OS_WIN + { + bool exit = false; + cleanupUpdate(parser, &exit); + if (exit) + return EXIT_SUCCESS; + } +#endif + if (parser.isSet(CommandLineOptions::scStartServerLong)) { const QStringList arguments = parser.value(CommandLineOptions::scStartServerLong) - .split(QLatin1Char(','), QString::SkipEmptyParts); + .split(QLatin1Char(','), Qt::SkipEmptyParts); QString socketName, key; const QString mode = arguments.value(0); @@ -267,6 +341,9 @@ int main(int argc, char *argv[]) } else if (parser.positionalArguments().contains(CommandLineOptions::scCreateOfflineShort) || parser.positionalArguments().contains(CommandLineOptions::scCreateOfflineLong)) { return CommandLineInterface(argc, argv).createOfflineInstaller(); + } else if (parser.positionalArguments().contains(CommandLineOptions::scClearCacheShort) + || parser.positionalArguments().contains(CommandLineOptions::scClearCacheLong)) { + return CommandLineInterface(argc, argv).clearLocalCache(); } if (QInstaller::LoggingHandler::instance().isVerbose()) { std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl; |