From 2690fc7c7669c46f326f01f356e71f9d3d1b7e80 Mon Sep 17 00:00:00 2001 From: Arttu Tarkiainen Date: Fri, 12 Feb 2021 15:17:39 +0200 Subject: CLI: Add warning when cli-only options are used without command keyword Task-number: QTIFW-2046 Change-Id: Id1c3d24e8c385bdfbe0a7837be774f885a192aa4 Reviewed-by: Katja Marttila --- src/libs/installer/commandlineparser.cpp | 106 +++++++++++++++++------------ src/libs/installer/commandlineparser.h | 14 +++- src/libs/installer/commandlineparser_p.cpp | 4 +- src/libs/installer/commandlineparser_p.h | 17 +++-- src/sdk/sdkapp.h | 10 +++ 5 files changed, 96 insertions(+), 55 deletions(-) diff --git a/src/libs/installer/commandlineparser.cpp b/src/libs/installer/commandlineparser.cpp index 9812023cb..59d42eefc 100644 --- a/src/libs/installer/commandlineparser.cpp +++ b/src/libs/installer/commandlineparser.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -40,7 +40,7 @@ static const QLatin1String scInstallerValue("InstallerValue"); } // namespace CommandLineOptions CommandLineParser::CommandLineParser() - : d(new CommandLineParserPrivate()) + : d(new CommandLineParserPrivate(this)) { static const QLatin1String indent(" "); static const QString preformatted = QLatin1String("\nQt Installer Framework supports both GUI and " @@ -68,17 +68,17 @@ CommandLineParser::CommandLineParser() // Help & version information m_parser.addHelpOption(); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scVersionShort << CommandLineOptions::scVersionLong, QLatin1String("Displays version information."))); // Output related options - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scVerboseShort << CommandLineOptions::scVerboseLong, QString::fromLatin1("Verbose mode. Prints out more information. Adding -%1 or --%2 more " "than once increases verbosity.").arg(CommandLineOptions::scVerboseShort, CommandLineOptions::scVerboseLong))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scLoggingRulesShort << CommandLineOptions::scLoggingRulesLong, QLatin1String("Enables logging according to passed rules. Comma separated logging rules " "have the following syntax: loggingCategory=true/false. Passing empty logging " @@ -88,15 +88,15 @@ CommandLineParser::CommandLineParser() QLatin1String("rules"))); // Repository management options - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scAddRepositoryShort << CommandLineOptions::scAddRepositoryLong, QLatin1String("Add a local or remote repository to the list of user defined repositories."), QLatin1String("URI,..."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scAddTmpRepositoryShort << CommandLineOptions::scAddTmpRepositoryLong, QLatin1String("Add a local or remote repository to the list of temporary available repositories."), QLatin1String("URI,..."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scSetTmpRepositoryShort << CommandLineOptions::scSetTmpRepositoryLong, QLatin1String("Set a local or remote repository as temporary repository, it is the only " "one used during fetch.\nNote: URI must be prefixed with the protocol, i.e. " @@ -104,111 +104,111 @@ CommandLineParser::CommandLineParser() QLatin1String("URI,..."))); // Proxy options - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scSystemProxyShort << CommandLineOptions::scSystemProxyLong, QLatin1String("Use system proxy on Windows and Linux. This option has no effect on macOS. (Default)"))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scNoProxyShort << CommandLineOptions::scNoProxyLong, QLatin1String("Do not use system proxy."))); // Starting mode options - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scStartUpdaterShort << CommandLineOptions::scStartUpdaterLong, QLatin1String("Start application in updater mode. This will override the internal " "marker that is used to distinguish which kind of binary is currently running."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scStartPackageManagerShort << CommandLineOptions::scStartPackageManagerLong, QLatin1String("Start application in package manager mode. This will override the internal " "marker that is used to distinguish which kind of binary is currently running."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scStartUninstallerShort << CommandLineOptions::scStartUninstallerLong, QLatin1String("Start application in uninstaller mode. This will override the internal " "marker that is used to distinguish which kind of binary is currently running."))); // Misc installation options - m_parser.addOption(QCommandLineOption(QStringList() + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scRootShort << CommandLineOptions::scRootLong, QLatin1String("[CLI] Set installation root directory."), - QLatin1String("directory"))); - m_parser.addOption(QCommandLineOption(QStringList() + QLatin1String("directory")), CommandLineOnly); + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scOfflineInstallerNameShort << CommandLineOptions::scOfflineInstallerNameLong, QLatin1String("[CLI] Set custom filename for the generated offline installer. Without this " "the original filename is used with an added \"_offline-yyyy-MM-dd\" suffix."), - QLatin1String("filename"))); - m_parser.addOption(QCommandLineOption(QStringList() + QLatin1String("filename")), CommandLineOnly); + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scPlatformShort << CommandLineOptions::scPlatformLong, QLatin1String("Use the specified platform plugin."), QLatin1String("plugin"))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scNoForceInstallationShort << CommandLineOptions::scNoForceInstallationLong, QLatin1String("Allow deselecting components that are marked as forced."))); - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scNoDefaultInstallationShort + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scNoDefaultInstallationShort << CommandLineOptions::scNoDefaultInstallationLong, QLatin1String("Deselects components that are marked as default."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scNoSizeCheckingShort << CommandLineOptions::scNoSizeCheckingLong, QLatin1String("Disable checking of free space for installation target."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scShowVirtualComponentsShort << CommandLineOptions::scShowVirtualComponentsLong, QLatin1String("Show virtual components in installer and package manager."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scInstallCompressedRepositoryShort << CommandLineOptions::scInstallCompressedRepositoryLong, QLatin1String("Installs QBSP or 7z file. The QBSP (Board Support Package) file must be a .7z " "file which contains a valid repository."), QLatin1String("URI,..."))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scCreateLocalRepositoryShort << CommandLineOptions::scCreateLocalRepositoryLong, QLatin1String("Create a local repository inside the installation directory. This option " "has no effect on online installers."))); // Message query options - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scAcceptMessageQueryShort + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scAcceptMessageQueryShort << CommandLineOptions::scAcceptMessageQueryLong, - QLatin1String("[CLI] Accepts all message queries without user input."))); - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scRejectMessageQueryShort + QLatin1String("[CLI] Accepts all message queries without user input.")), CommandLineOnly); + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scRejectMessageQueryShort << CommandLineOptions::scRejectMessageQueryLong, - QLatin1String("[CLI] Rejects all message queries without user input."))); - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scMessageAutomaticAnswerShort + QLatin1String("[CLI] Rejects all message queries without user input.")), CommandLineOnly); + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scMessageAutomaticAnswerShort << CommandLineOptions::scMessageAutomaticAnswerLong, QLatin1String("[CLI] Automatically answers the message queries with the message identifier and button value. " "Several identifier=value pairs can be given separated with comma, " "for example --auto-answer message.id=Ok,message.id2=Cancel."), - QLatin1String("identifier=value"))); - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scMessageDefaultAnswerShort + QLatin1String("identifier=value")), CommandLineOnly); + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scMessageDefaultAnswerShort << CommandLineOptions::scMessageDefaultAnswerLong, - QLatin1String("[CLI] Automatically answers to message queries with their default values."))); - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scAcceptLicensesShort + QLatin1String("[CLI] Automatically answers to message queries with their default values.")), CommandLineOnly); + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scAcceptLicensesShort << CommandLineOptions::scAcceptLicensesLong, - QLatin1String("[CLI] Accepts all licenses without user input."))); - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scFileDialogAutomaticAnswer, + QLatin1String("[CLI] Accepts all licenses without user input.")), CommandLineOnly); + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scFileDialogAutomaticAnswer, QLatin1String("[CLI] Automatically sets the QFileDialog values getExistingDirectory() or getOpenFileName() " "requested by install script. " "Several identifier=value pairs can be given separated with comma, " "for example --file-query filedialog.id=C:\Temp,filedialog.id2=C:\Temp2"), - QLatin1String("identifier=value"))); - m_parser.addOption(QCommandLineOption(QStringList() << CommandLineOptions::scConfirmCommandShort + QLatin1String("identifier=value")), CommandLineOnly); + addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scConfirmCommandShort << CommandLineOptions::scConfirmCommandLong, QLatin1String("[CLI] Confirms starting of " - "installation, update or removal of components without user input."))); + "installation, update or removal of components without user input.")), CommandLineOnly); // Developer options - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scScriptShort << CommandLineOptions::scScriptLong, QLatin1String("Execute the script given as argument."), QLatin1String("file"))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scStartServerShort << CommandLineOptions::scStartServerLong, QLatin1String("Starts the application as headless process waiting for commands to execute. Mode " "can be DEBUG or PRODUCTION. In DEBUG mode, the option values can be omitted. Note: " "The server will not shutdown on his own, you need to quit the process by hand."), QLatin1String("mode, socketname, key"))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scStartClientShort << CommandLineOptions::scStartClientLong, QLatin1String("Starts the application to debug the client-server communication. If a value is " "omitted, the client will use a default instead. Note: The server process is not " "started by the client application in that case, you need to start it on your own."), QLatin1String("socketname, key"))); - m_parser.addOption(QCommandLineOption(QStringList() + addOption(QCommandLineOption(QStringList() << CommandLineOptions::scSquishPortShort << CommandLineOptions::scSquishPortLong, QLatin1String("Give a port where Squish can connect to. If no port is given, default port 11233 is " "used. Note: To enable Squish support you first need to build IFW with SQUISH_PATH " @@ -219,14 +219,14 @@ CommandLineParser::CommandLineParser() // Deprecated options QCommandLineOption deprecatedUpdater(CommandLineOptions::scDeprecatedUpdater); deprecatedUpdater.setHidden(true); - m_parser.addOption(deprecatedUpdater); + addOption(deprecatedUpdater); QCommandLineOption deprecatedCheckUpdates(CommandLineOptions::scDeprecatedCheckUpdates); deprecatedCheckUpdates.setHidden(true); - m_parser.addOption(deprecatedCheckUpdates); // Behaves like check-updates but does not default to verbose output + addOption(deprecatedCheckUpdates); // Behaves like check-updates but does not default to verbose output // Custom extension options - m_parser.addOptions(d->extensionsOptions()); + d->addExtensionsOptions(); // Positional arguments m_parser.addPositionalArgument(CommandLineOptions::scCommand, @@ -244,3 +244,19 @@ CommandLineParser::~CommandLineParser() { delete d; } + +bool CommandLineParser::addOptionWithContext(const QCommandLineOption &option, CommandLineParser::OptionContextFlags flags) +{ + if (!m_parser.addOption(option)) + return false; + + for (auto &name : option.names()) + m_optionContextFlagsNameHash.insert(name, flags); + + return true; +} + +CommandLineParser::OptionContextFlags CommandLineParser::optionContextFlags(const QString &option) const +{ + return m_optionContextFlagsNameHash.value(option); +} diff --git a/src/libs/installer/commandlineparser.h b/src/libs/installer/commandlineparser.h index d1ad31eb5..8f112fcb9 100644 --- a/src/libs/installer/commandlineparser.h +++ b/src/libs/installer/commandlineparser.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -36,9 +36,17 @@ class CommandLineParser { public: + enum OptionContextFlag { + CommandLineOnly = 0x1 + }; + Q_DECLARE_FLAGS(OptionContextFlags, OptionContextFlag) + CommandLineParser(); ~CommandLineParser(); + bool addOption(const QCommandLineOption &option) { return m_parser.addOption(option); } + bool addOptionWithContext(const QCommandLineOption &option, OptionContextFlags flags); + QString helpText() const { return m_parser.helpText(); } bool isSet(const QString &option) { return m_parser.isSet(option); } QStringList unknownOptionNames() const { return m_parser.unknownOptionNames(); } @@ -47,9 +55,13 @@ public: QString value(const QString &option) const { return m_parser.value(option); } QStringList optionNames() const { return m_parser.optionNames(); } + OptionContextFlags optionContextFlags(const QString &option) const; + private: QCommandLineParser m_parser; class CommandLineParserPrivate *const d; + + QHash m_optionContextFlagsNameHash; }; #endif // COMMANDLINEPARSER_H diff --git a/src/libs/installer/commandlineparser_p.cpp b/src/libs/installer/commandlineparser_p.cpp index de9ca45dd..a6b2a4a50 100644 --- a/src/libs/installer/commandlineparser_p.cpp +++ b/src/libs/installer/commandlineparser_p.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -28,6 +28,6 @@ #include "commandlineparser_p.h" -CommandLineParserPrivate::CommandLineParserPrivate() +void CommandLineParserPrivate::addExtensionsOptions() const { } diff --git a/src/libs/installer/commandlineparser_p.h b/src/libs/installer/commandlineparser_p.h index 1c050a389..3c0016b96 100644 --- a/src/libs/installer/commandlineparser_p.h +++ b/src/libs/installer/commandlineparser_p.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -29,20 +29,23 @@ #ifndef COMMANDLINEPARSER_P_H #define COMMANDLINEPARSER_P_H +#include "commandlineparser.h" + #include +class CommandLineParser; + class CommandLineParserPrivate { + Q_DISABLE_COPY(CommandLineParserPrivate) + public: - CommandLineParserPrivate(); + explicit CommandLineParserPrivate(CommandLineParser *parser) : q(parser) {}; - QList &extensionsOptions() - { - return m_extensionOptions; - } + void addExtensionsOptions() const; private: - QList m_extensionOptions; + CommandLineParser *const q; }; #endif // COMMANDLINEPARSER_P_H diff --git a/src/sdk/sdkapp.h b/src/sdk/sdkapp.h index ad40e0a42..e35759e0f 100644 --- a/src/sdk/sdkapp.h +++ b/src/sdk/sdkapp.h @@ -173,6 +173,16 @@ public: qCDebug(QInstaller::lcInstallerInstallLog).noquote() << "Arguments:" << QCoreApplication::arguments().join(QLatin1String(", ")); + for (auto &optionName : m_parser.optionNames()) { + if (isCommandLineInterface) + break; + + if (m_parser.optionContextFlags(optionName) & CommandLineParser::CommandLineOnly) { + qCWarning(QInstaller::lcInstallerInstallLog).nospace() << "Found command line only option " + << optionName << ". This will not have any effect when running in graphical mode."; + } + } + dumpResourceTree(); SDKApp::registerMetaResources(manager.collectionByName("QResources")); -- cgit v1.2.3