From 6ff1723c4cb709ebffe2bb0c593371c51e6cf736 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 28 Feb 2022 17:07:24 +0100 Subject: [PATCH] ProcessInterface: Move out default impl into separate class Introduce private DefaultImpl class and base QProcessImpl and ProcessLauncherImpl on it. Remove default impl specific methods from ProcessInterface. Change-Id: Iea964ab19cc0ea8401180f65351b6ef3f595703f Reviewed-by: hjk --- src/libs/utils/processinterface.h | 9 +- src/libs/utils/qtcprocess.cpp | 221 +++++++++++++++--------------- 2 files changed, 115 insertions(+), 115 deletions(-) diff --git a/src/libs/utils/processinterface.h b/src/libs/utils/processinterface.h index 7b2999c69c4..e2dc99520d1 100644 --- a/src/libs/utils/processinterface.h +++ b/src/libs/utils/processinterface.h @@ -69,7 +69,7 @@ class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject public: ProcessInterface(QObject *parent = nullptr) : QObject(parent) {} - virtual void start() { defaultStart(); } + virtual void start() = 0; virtual void terminate() = 0; virtual void kill() = 0; virtual void close() = 0; @@ -103,14 +103,7 @@ signals: void readyReadStandardError(); protected: - void defaultStart(); - ProcessSetupData m_setup; - -private: - virtual void doDefaultStart(const QString &program, const QStringList &arguments); - bool dissolveCommand(QString *program, QStringList *arguments); - bool ensureProgramExists(const QString &program); friend class QtcProcess; }; diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index f40aab99cb4..151c83cad26 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -275,7 +275,119 @@ private: Internal::TerminalProcess m_terminal; }; -class QProcessImpl : public ProcessInterface +class DefaultImpl : public ProcessInterface +{ +public: + virtual void start() { defaultStart(); } + +protected: + void defaultStart(); + +private: + virtual void doDefaultStart(const QString &program, const QStringList &arguments) = 0; + bool dissolveCommand(QString *program, QStringList *arguments); + bool ensureProgramExists(const QString &program); +}; + +static QString blockingMessage(const QVariant &variant) +{ + if (!variant.isValid()) + return "non blocking"; + if (variant.toInt() == int(QtcProcess::WithEventLoop)) + return "blocking with event loop"; + return "blocking without event loop"; +} + +void DefaultImpl::defaultStart() +{ + if (processLog().isDebugEnabled()) { + using namespace std::chrono; + const quint64 msSinceEpoc = + duration_cast(system_clock::now().time_since_epoch()).count(); + setProperty(QTC_PROCESS_STARTTIME, msSinceEpoc); + + static std::atomic_int startCounter = 0; + const int currentNumber = startCounter.fetch_add(1); + qCDebug(processLog).nospace().noquote() + << "Process " << currentNumber << " starting (" + << qPrintable(blockingMessage(property(QTC_PROCESS_BLOCKING_TYPE))) + << "): " + << m_setup.m_commandLine.toUserOutput(); + setProperty(QTC_PROCESS_NUMBER, currentNumber); + } + + QString program; + QStringList arguments; + if (!dissolveCommand(&program, &arguments)) + return; + if (!ensureProgramExists(program)) + return; + s_start.measureAndRun(&DefaultImpl::doDefaultStart, this, program, arguments); +} + +bool DefaultImpl::dissolveCommand(QString *program, QStringList *arguments) +{ + const CommandLine &commandLine = m_setup.m_commandLine; + QString commandString; + ProcessArgs processArgs; + const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &processArgs, + &m_setup.m_environment, + &m_setup.m_workingDirectory); + + if (commandLine.executable().osType() == OsTypeWindows) { + QString args; + if (m_setup.m_useCtrlCStub) { + if (m_setup.m_lowPriority) + ProcessArgs::addArg(&args, "-nice"); + ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString)); + commandString = QCoreApplication::applicationDirPath() + + QLatin1String("/qtcreator_ctrlc_stub.exe"); + } else if (m_setup.m_lowPriority) { + m_setup.m_belowNormalPriority = true; + } + ProcessArgs::addArgs(&args, processArgs.toWindowsArgs()); + m_setup.m_nativeArguments = args; + // Note: Arguments set with setNativeArgs will be appended to the ones + // passed with start() below. + *arguments = QStringList(); + } else { + if (!success) { + setErrorString(tr("Error in command line.")); + // TODO: in fact it's WrongArgumentsFailure + emit errorOccurred(QProcess::FailedToStart); + return false; + } + *arguments = processArgs.toUnixArgs(); + } + *program = commandString; + return true; +} + +static FilePath resolve(const FilePath &workingDir, const FilePath &filePath) +{ + if (filePath.isAbsolutePath()) + return filePath; + + const FilePath fromWorkingDir = workingDir.resolvePath(filePath); + if (fromWorkingDir.exists() && fromWorkingDir.isExecutableFile()) + return fromWorkingDir; + return filePath.searchInPath(); +} + +bool DefaultImpl::ensureProgramExists(const QString &program) +{ + const FilePath programFilePath = resolve(m_setup.m_workingDirectory, + FilePath::fromString(program)); + if (programFilePath.exists() && programFilePath.isExecutableFile()) + return true; + + setErrorString(QLatin1String("The program \"%1\" does not exist or is not executable.") + .arg(program)); + emit errorOccurred(QProcess::FailedToStart); + return false; +} + +class QProcessImpl : public DefaultImpl { public: QProcessImpl() : m_process(new ProcessHelper(this)) @@ -366,7 +478,7 @@ static uint uniqueToken() return ++globalUniqueToken; } -class ProcessLauncherImpl : public ProcessInterface +class ProcessLauncherImpl : public DefaultImpl { Q_OBJECT public: @@ -572,15 +684,6 @@ QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode) } // Internal -static QString blockingMessage(const QVariant &variant) -{ - if (!variant.isValid()) - return "non blocking"; - if (variant.toInt() == int(QtcProcess::WithEventLoop)) - return "blocking with event loop"; - return "blocking without event loop"; -} - void ProcessInterface::kickoffProcess() { QTC_CHECK(false); @@ -596,102 +699,6 @@ qint64 ProcessInterface::applicationMainThreadID() const QTC_CHECK(false); return -1; } -void ProcessInterface::defaultStart() -{ - if (processLog().isDebugEnabled()) { - using namespace std::chrono; - const quint64 msSinceEpoc = - duration_cast(system_clock::now().time_since_epoch()).count(); - setProperty(QTC_PROCESS_STARTTIME, msSinceEpoc); - - static std::atomic_int startCounter = 0; - const int currentNumber = startCounter.fetch_add(1); - qCDebug(processLog).nospace().noquote() - << "Process " << currentNumber << " starting (" - << qPrintable(blockingMessage(property(QTC_PROCESS_BLOCKING_TYPE))) - << "): " - << m_setup.m_commandLine.toUserOutput(); - setProperty(QTC_PROCESS_NUMBER, currentNumber); - } - - QString program; - QStringList arguments; - if (!dissolveCommand(&program, &arguments)) - return; - if (!ensureProgramExists(program)) - return; - s_start.measureAndRun(&ProcessInterface::doDefaultStart, this, program, arguments); -} - -void ProcessInterface::doDefaultStart(const QString &program, const QStringList &arguments) -{ - Q_UNUSED(program) - Q_UNUSED(arguments) - QTC_CHECK(false); -} - -bool ProcessInterface::dissolveCommand(QString *program, QStringList *arguments) -{ - const CommandLine &commandLine = m_setup.m_commandLine; - QString commandString; - ProcessArgs processArgs; - const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &processArgs, - &m_setup.m_environment, - &m_setup.m_workingDirectory); - - if (commandLine.executable().osType() == OsTypeWindows) { - QString args; - if (m_setup.m_useCtrlCStub) { - if (m_setup.m_lowPriority) - ProcessArgs::addArg(&args, "-nice"); - ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString)); - commandString = QCoreApplication::applicationDirPath() - + QLatin1String("/qtcreator_ctrlc_stub.exe"); - } else if (m_setup.m_lowPriority) { - m_setup.m_belowNormalPriority = true; - } - ProcessArgs::addArgs(&args, processArgs.toWindowsArgs()); - m_setup.m_nativeArguments = args; - // Note: Arguments set with setNativeArgs will be appended to the ones - // passed with start() below. - *arguments = QStringList(); - } else { - if (!success) { - setErrorString(tr("Error in command line.")); - // TODO: in fact it's WrongArgumentsFailure - emit errorOccurred(QProcess::FailedToStart); - return false; - } - *arguments = processArgs.toUnixArgs(); - } - *program = commandString; - return true; -} - -static FilePath resolve(const FilePath &workingDir, const FilePath &filePath) -{ - if (filePath.isAbsolutePath()) - return filePath; - - const FilePath fromWorkingDir = workingDir.resolvePath(filePath); - if (fromWorkingDir.exists() && fromWorkingDir.isExecutableFile()) - return fromWorkingDir; - return filePath.searchInPath(); -} - -bool ProcessInterface::ensureProgramExists(const QString &program) -{ - const FilePath programFilePath = resolve(m_setup.m_workingDirectory, - FilePath::fromString(program)); - if (programFilePath.exists() && programFilePath.isExecutableFile()) - return true; - - setErrorString(QLatin1String("The program \"%1\" does not exist or is not executable.") - .arg(program)); - emit errorOccurred(QProcess::FailedToStart); - return false; -} - /*! \class Utils::QtcProcess