diff options
author | Jarek Kobus <jaroslaw.kobus@qt.io> | 2022-07-29 14:41:15 +0200 |
---|---|---|
committer | Jarek Kobus <jaroslaw.kobus@qt.io> | 2022-07-29 14:52:02 +0000 |
commit | 0a1ac481ede9499e8cd86148c4195109e06d6431 (patch) | |
tree | 32110a5e96e09ad8dab7701d02578cbe65d29a0c | |
parent | 278f33d5210470cfcb82b9a1575722eb06ad2897 (diff) | |
download | qt-creator-0a1ac481ede9499e8cd86148c4195109e06d6431.tar.gz |
ShellCommand: Introduce CommandResult structure
Don't require QtcProcess instance when calling
ShellCommand::runCommand().
Change-Id: Ie0287d91c1807465eab12be7eaa2eac561179af7
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
-rw-r--r-- | src/libs/utils/shellcommand.cpp | 37 | ||||
-rw-r--r-- | src/libs/utils/shellcommand.h | 30 | ||||
-rw-r--r-- | src/plugins/bazaar/bazaarclient.cpp | 16 | ||||
-rw-r--r-- | src/plugins/clearcase/clearcaseplugin.cpp | 14 | ||||
-rw-r--r-- | src/plugins/cvs/cvsplugin.cpp | 15 | ||||
-rw-r--r-- | src/plugins/git/gerrit/gerritserver.cpp | 29 | ||||
-rw-r--r-- | src/plugins/git/gitclient.cpp | 391 | ||||
-rw-r--r-- | src/plugins/git/gitgrep.cpp | 8 | ||||
-rw-r--r-- | src/plugins/mercurial/mercurialclient.cpp | 72 | ||||
-rw-r--r-- | src/plugins/subversion/subversionclient.cpp | 36 | ||||
-rw-r--r-- | src/plugins/subversion/subversionplugin.cpp | 16 | ||||
-rw-r--r-- | src/plugins/vcsbase/vcsbaseclient.cpp | 63 | ||||
-rw-r--r-- | src/plugins/vcsbase/vcsbaseclient.h | 24 |
13 files changed, 354 insertions, 397 deletions
diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp index e7c74e02d3..15df0c63e3 100644 --- a/src/libs/utils/shellcommand.cpp +++ b/src/libs/utils/shellcommand.cpp @@ -260,13 +260,11 @@ void ShellCommand::run(QFutureInterface<void> &future) bool lastExecSuccess = true; for (int j = 0; j < count; j++) { const Internal::ShellCommandPrivate::Job &job = d->m_jobs.at(j); - QtcProcess proc; - proc.setExitCodeInterpreter(job.exitCodeInterpreter); - proc.setTimeoutS(job.timeoutS); - runCommand(proc, job.command, job.workingDirectory); - stdOut += proc.cleanedStdOut(); - stdErr += proc.cleanedStdErr(); - lastExecSuccess = proc.result() == ProcessResult::FinishedWithSuccess; + const CommandResult result = runCommand(job.command, job.workingDirectory, + job.timeoutS, job.exitCodeInterpreter); + stdOut += result.cleanedStdOut(); + stdErr += result.cleanedStdErr(); + lastExecSuccess = result.result() == ProcessResult::FinishedWithSuccess; if (!lastExecSuccess) break; } @@ -291,14 +289,15 @@ void ShellCommand::run(QFutureInterface<void> &future) this->deleteLater(); } -void ShellCommand::runCommand(QtcProcess &proc, - const CommandLine &command, - const FilePath &workingDirectory) +CommandResult ShellCommand::runCommand(const CommandLine &command, const FilePath &workingDirectory, + int timeoutS, const ExitCodeInterpreter &interpreter) { - if (command.executable().isEmpty()) { - proc.setResult(ProcessResult::StartFailed); - return; - } + QtcProcess proc; + if (command.executable().isEmpty()) + return {}; + + proc.setExitCodeInterpreter(interpreter); + proc.setTimeoutS(timeoutS); const FilePath dir = workDirectory(workingDirectory); if (!dir.isEmpty()) @@ -334,6 +333,7 @@ void ShellCommand::runCommand(QtcProcess &proc, } } emit runCommandFinished(dir); + return {proc}; } void ShellCommand::runFullySynchronous(QtcProcess &process) @@ -458,4 +458,13 @@ void ProgressParser::setFuture(QFutureInterface<void> *future) m_future = future; } +CommandResult::CommandResult(const QtcProcess &process) + : m_result(process.result()) + , m_exitCode(process.exitCode()) + , m_exitMessage(process.exitMessage()) + , m_cleanedStdOut(process.cleanedStdOut()) + , m_cleanedStdErr(process.cleanedStdErr()) + , m_rawStdOut(process.rawStdOut()) +{} + } // namespace Utils diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h index 3cf4e5c23b..bcc8a80ecd 100644 --- a/src/libs/utils/shellcommand.h +++ b/src/libs/utils/shellcommand.h @@ -68,6 +68,32 @@ private: friend class ShellCommand; }; +class QTCREATOR_UTILS_EXPORT CommandResult +{ +public: + CommandResult() = default; + CommandResult(const QtcProcess &process); + + ProcessResult result() const { return m_result; } + int exitCode() const { return m_exitCode; } + QString exitMessage() const { return m_exitMessage; } + + QString cleanedStdOut() const { return m_cleanedStdOut; } + QString cleanedStdErr() const { return m_cleanedStdErr; } + + QByteArray rawStdOut() const { return m_rawStdOut; } + +private: + ProcessResult m_result = ProcessResult::StartFailed; + int m_exitCode = 0; + QString m_exitMessage; + + QString m_cleanedStdOut; + QString m_cleanedStdErr; + + QByteArray m_rawStdOut; +}; + class QTCREATOR_UTILS_EXPORT ShellCommand final : public QObject { Q_OBJECT @@ -131,8 +157,8 @@ public: // This is called once per job in a thread. // When called from the UI thread it will execute fully synchronously, so no signals will // be triggered! - void runCommand(QtcProcess &process, const CommandLine &command, - const FilePath &workingDirectory = {}); + CommandResult runCommand(const CommandLine &command, const FilePath &workingDirectory = {}, + int timeoutS = 10, const ExitCodeInterpreter &interpreter = {}); void cancel(); diff --git a/src/plugins/bazaar/bazaarclient.cpp b/src/plugins/bazaar/bazaarclient.cpp index ccd91a236f..5dc14d9f64 100644 --- a/src/plugins/bazaar/bazaarclient.cpp +++ b/src/plugins/bazaar/bazaarclient.cpp @@ -31,7 +31,7 @@ #include <vcsbase/vcsbaseeditorconfig.h> #include <utils/hostosinfo.h> -#include <utils/qtcprocess.h> +#include <utils/shellcommand.h> #include <QDir> #include <QFileInfo> @@ -151,10 +151,9 @@ bool BazaarClient::synchronousUncommit(const FilePath &workingDir, << revisionSpec(revision) << extraOptions; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDir, args); - VcsOutputWindow::append(proc.cleanedStdOut()); - return proc.result() == ProcessResult::FinishedWithSuccess; + const CommandResult result = vcsFullySynchronousExec(workingDir, args); + VcsOutputWindow::append(result.cleanedStdOut()); + return result.result() == ProcessResult::FinishedWithSuccess; } void BazaarClient::commit(const FilePath &repositoryRoot, const QStringList &files, @@ -190,11 +189,10 @@ bool BazaarClient::managesFile(const FilePath &workingDirectory, const QString & QStringList args(QLatin1String("status")); args << fileName; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, args); - if (proc.result() != ProcessResult::FinishedWithSuccess) + const CommandResult result = vcsFullySynchronousExec(workingDirectory, args); + if (result.result() != ProcessResult::FinishedWithSuccess) return false; - return proc.rawStdOut().startsWith("unknown"); + return result.rawStdOut().startsWith("unknown"); } void BazaarClient::view(const QString &source, const QString &id, const QStringList &extraOptions) diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index 89bd490b8c..b75ac20cec 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -1666,20 +1666,18 @@ ClearCasePluginPrivate::runCleartool(const FilePath &workingDir, return response; } - QtcProcess proc; - proc.setTimeoutS(timeOutS); - auto *command = VcsBaseClient::createVcsCommand(workingDir, Environment::systemEnvironment()); command->addFlags(flags); command->setCodec(outputCodec); - command->runCommand(proc, {FilePath::fromString(executable), arguments}); + const CommandResult result = command->runCommand({FilePath::fromString(executable), arguments}, + workingDir, timeOutS); delete command; - response.error = proc.result() != ProcessResult::FinishedWithSuccess; + response.error = result.result() != ProcessResult::FinishedWithSuccess; if (response.error) - response.message = proc.exitMessage(); - response.stdErr = proc.cleanedStdErr(); - response.stdOut = proc.cleanedStdOut(); + response.message = result.exitMessage(); + response.stdErr = result.cleanedStdErr(); + response.stdOut = result.cleanedStdOut(); return response; } diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index 573008a3a7..2ee2e64ec7 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -53,11 +53,11 @@ #include <coreplugin/locator/commandlocator.h> #include <coreplugin/vcsmanager.h> +#include <utils/commandline.h> #include <utils/environment.h> #include <utils/fileutils.h> #include <utils/parameteraction.h> #include <utils/qtcassert.h> -#include <utils/qtcprocess.h> #include <utils/shellcommand.h> #include <utils/stringutils.h> @@ -1432,20 +1432,19 @@ CvsResponse CvsPluginPrivate::runCvs(const FilePath &workingDirectory, return response; } // Run, connect stderr to the output window - QtcProcess proc; - proc.setTimeoutS(timeOutS); auto *command = VcsBaseClient::createVcsCommand(workingDirectory, Environment::systemEnvironment()); command->addFlags(flags); command->setCodec(outputCodec); - command->runCommand(proc, {executable, m_settings.addOptions(arguments)}); + const CommandResult result = command->runCommand({executable, m_settings.addOptions(arguments)}, + workingDirectory, timeOutS); delete command; response.result = CvsResponse::OtherError; - response.stdErr = proc.cleanedStdErr(); - response.stdOut = proc.cleanedStdOut(); - switch (proc.result()) { + response.stdErr = result.cleanedStdErr(); + response.stdOut = result.cleanedStdOut(); + switch (result.result()) { case ProcessResult::FinishedWithSuccess: response.result = CvsResponse::Ok; break; @@ -1459,7 +1458,7 @@ CvsResponse CvsPluginPrivate::runCvs(const FilePath &workingDirectory, } if (response.result != CvsResponse::Ok) - response.message = proc.exitMessage(); + response.message = result.exitMessage(); return response; } diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp index 3dd5e6e5cb..78a67471f9 100644 --- a/src/plugins/git/gerrit/gerritserver.cpp +++ b/src/plugins/git/gerrit/gerritserver.cpp @@ -26,13 +26,12 @@ #include "authenticationdialog.h" #include "gerritparameters.h" #include "gerritserver.h" -#include "../gitplugin.h" #include "../gitclient.h" #include <coreplugin/icore.h> +#include <utils/commandline.h> #include <utils/hostosinfo.h> -#include <utils/qtcprocess.h> #include <utils/shellcommand.h> #include <QFile> @@ -243,10 +242,10 @@ int GerritServer::testConnection() { static GitClient *const client = GitClient::instance(); const QStringList arguments = curlArguments() << (url(RestUrl) + accountUrlC); - QtcProcess proc; - client->vcsFullySynchronousExec(proc, {}, {curlBinary, arguments}, ShellCommand::NoOutput); - if (proc.result() == ProcessResult::FinishedWithSuccess) { - QString output = proc.cleanedStdOut(); + const CommandResult result = client->vcsFullySynchronousExec({}, {curlBinary, arguments}, + ShellCommand::NoOutput); + if (result.result() == ProcessResult::FinishedWithSuccess) { + QString output = result.cleanedStdOut(); // Gerrit returns an empty response for /p/qt-creator/a/accounts/self // so consider this as 404. if (output.isEmpty()) @@ -262,10 +261,10 @@ int GerritServer::testConnection() } return Success; } - if (proc.exitCode() == CertificateError) + if (result.exitCode() == CertificateError) return CertificateError; const QRegularExpression errorRegexp("returned error: (\\d+)"); - QRegularExpressionMatch match = errorRegexp.match(proc.cleanedStdErr()); + QRegularExpressionMatch match = errorRegexp.match(result.cleanedStdErr()); if (match.hasMatch()) return match.captured(1).toInt(); return UnknownError; @@ -339,25 +338,25 @@ bool GerritServer::resolveVersion(const GerritParameters &p, bool forceReload) if (!version.isEmpty() && !forceReload) return true; if (type == Ssh) { - QtcProcess proc; QStringList arguments; if (port) arguments << p.portFlag << QString::number(port); arguments << hostArgument() << "gerrit" << "version"; - client->vcsFullySynchronousExec(proc, {}, {p.ssh, arguments}, ShellCommand::NoOutput); - QString stdOut = proc.cleanedStdOut().trimmed(); + const CommandResult result = client->vcsFullySynchronousExec({}, {p.ssh, arguments}, + ShellCommand::NoOutput); + QString stdOut = result.cleanedStdOut().trimmed(); stdOut.remove("gerrit version "); version = stdOut; if (version.isEmpty()) return false; } else { const QStringList arguments = curlArguments() << (url(RestUrl) + versionUrlC); - QtcProcess proc; - client->vcsFullySynchronousExec(proc, {}, {curlBinary, arguments}, ShellCommand::NoOutput); + const CommandResult result = client->vcsFullySynchronousExec({}, {curlBinary, arguments}, + ShellCommand::NoOutput); // REST endpoint for version is only available from 2.8 and up. Do not consider invalid // if it fails. - if (proc.result() == ProcessResult::FinishedWithSuccess) { - QString output = proc.cleanedStdOut(); + if (result.result() == ProcessResult::FinishedWithSuccess) { + QString output = result.cleanedStdOut(); if (output.isEmpty()) return false; output.remove(0, output.indexOf('\n')); // Strip first line diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 3a5175fdfd..6f8d31d6fe 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -752,16 +752,16 @@ public: connect(command, &ShellCommand::stdErrText, handler, &ConflictHandler::readStdErr); } - static void handleResponse(const Utils::QtcProcess &proc, + static void handleResponse(const Utils::CommandResult &result, const FilePath &workingDirectory, const QString &abortCommand = QString()) { ConflictHandler handler(workingDirectory, abortCommand); // No conflicts => do nothing - if (proc.result() == ProcessResult::FinishedWithSuccess) + if (result.result() == ProcessResult::FinishedWithSuccess) return; - handler.readStdOut(proc.cleanedStdOut()); - handler.readStdErr(proc.cleanedStdErr()); + handler.readStdOut(result.cleanedStdOut()); + handler.readStdErr(result.cleanedStdErr()); } private: @@ -921,10 +921,9 @@ QString GitClient::findGitDirForRepository(const FilePath &repositoryDir) const bool GitClient::managesFile(const FilePath &workingDirectory, const QString &fileName) const { - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, {"ls-files", "--error-unmatch", fileName}, - ShellCommand::NoOutput); - return proc.result() == ProcessResult::FinishedWithSuccess; + const CommandResult result = vcsFullySynchronousExec(workingDirectory, + {"ls-files", "--error-unmatch", fileName}, ShellCommand::NoOutput); + return result.result() == ProcessResult::FinishedWithSuccess; } FilePaths GitClient::unmanagedFiles(const FilePaths &filePaths) const @@ -938,12 +937,11 @@ FilePaths GitClient::unmanagedFiles(const FilePaths &filePaths) const QStringList args({"ls-files", "-z"}); const QDir wd(it.key().toString()); args << transform(it.value(), [&wd](const QString &fp) { return wd.relativeFilePath(fp); }); - QtcProcess proc; - vcsFullySynchronousExec(proc, it.key(), args, ShellCommand::NoOutput); - if (proc.result() != ProcessResult::FinishedWithSuccess) + const CommandResult result = vcsFullySynchronousExec(it.key(), args, ShellCommand::NoOutput); + if (result.result() != ProcessResult::FinishedWithSuccess) return filePaths; const QStringList managedFilePaths - = transform(proc.cleanedStdOut().split('\0', Qt::SkipEmptyParts), + = transform(result.cleanedStdOut().split('\0', Qt::SkipEmptyParts), [&wd](const QString &fp) { return wd.absoluteFilePath(fp); }); const QStringList filtered = Utils::filtered(it.value(), [&managedFilePaths, &wd](const QString &fp) { return !managedFilePaths.contains(wd.absoluteFilePath(fp)); @@ -1514,11 +1512,10 @@ void GitClient::removeStaleRemoteBranches(const FilePath &workingDirectory, cons void GitClient::recoverDeletedFiles(const FilePath &workingDirectory) { - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, {"ls-files", "--deleted"}, + const CommandResult result = vcsFullySynchronousExec(workingDirectory, {"ls-files", "--deleted"}, ShellCommand::SuppressCommandLogging); - if (proc.result() == ProcessResult::FinishedWithSuccess) { - const QString stdOut = proc.cleanedStdOut().trimmed(); + if (result.result() == ProcessResult::FinishedWithSuccess) { + const QString stdOut = result.cleanedStdOut().trimmed(); if (stdOut.isEmpty()) { VcsOutputWindow::appendError(tr("Nothing to recover")); return; @@ -1541,17 +1538,15 @@ bool GitClient::synchronousLog(const FilePath &workingDirectory, const QStringLi allArguments.append(arguments); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, allArguments, flags, vcsTimeoutS(), - encoding(workingDirectory, "i18n.logOutputEncoding")); - if (proc.result() == ProcessResult::FinishedWithSuccess) { - *output = proc.cleanedStdOut(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, allArguments, + flags, vcsTimeoutS(), encoding(workingDirectory, "i18n.logOutputEncoding")); + if (result.result() == ProcessResult::FinishedWithSuccess) { + *output = result.cleanedStdOut(); return true; - } else { - msgCannotRun(tr("Cannot obtain log of \"%1\": %2") - .arg(workingDirectory.toUserOutput(), proc.cleanedStdErr()), errorMessageIn); - return false; } + msgCannotRun(tr("Cannot obtain log of \"%1\": %2") + .arg(workingDirectory.toUserOutput(), result.cleanedStdErr()), errorMessageIn); + return false; } bool GitClient::synchronousAdd(const FilePath &workingDirectory, @@ -1560,9 +1555,8 @@ bool GitClient::synchronousAdd(const FilePath &workingDirectory, { QStringList args{"add"}; args += extraOptions + files; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, args); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsFullySynchronousExec(workingDirectory, args).result() + == ProcessResult::FinishedWithSuccess; } bool GitClient::synchronousDelete(const FilePath &workingDirectory, @@ -1573,18 +1567,16 @@ bool GitClient::synchronousDelete(const FilePath &workingDirectory, if (force) arguments << "--force"; arguments.append(files); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsFullySynchronousExec(workingDirectory, arguments).result() + == ProcessResult::FinishedWithSuccess; } bool GitClient::synchronousMove(const FilePath &workingDirectory, const QString &from, const QString &to) { - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, {"mv", from, to}); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsFullySynchronousExec(workingDirectory, {"mv", from, to}).result() + == ProcessResult::FinishedWithSuccess; } bool GitClient::synchronousReset(const FilePath &workingDirectory, @@ -1597,20 +1589,19 @@ bool GitClient::synchronousReset(const FilePath &workingDirectory, else arguments << HEAD << "--" << files; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments); - const QString stdOut = proc.cleanedStdOut(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments); + const QString stdOut = result.cleanedStdOut(); VcsOutputWindow::append(stdOut); // Note that git exits with 1 even if the operation is successful // Assume real failure if the output does not contain "foo.cpp modified" // or "Unstaged changes after reset" (git 1.7.0). - if (proc.result() != ProcessResult::FinishedWithSuccess + if (result.result() != ProcessResult::FinishedWithSuccess && (!stdOut.contains("modified") && !stdOut.contains("Unstaged changes after reset"))) { if (files.isEmpty()) { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage); + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), errorMessage); } else { msgCannotRun(tr("Cannot reset %n files in \"%1\": %2", nullptr, files.size()) - .arg(workingDirectory.toUserOutput(), proc.cleanedStdErr()), + .arg(workingDirectory.toUserOutput(), result.cleanedStdErr()), errorMessage); } return false; @@ -1621,16 +1612,14 @@ bool GitClient::synchronousReset(const FilePath &workingDirectory, // Initialize repository bool GitClient::synchronousInit(const FilePath &workingDirectory) { - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, QStringList{"init"}); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, QStringList{"init"}); // '[Re]Initialized...' - VcsOutputWindow::append(proc.cleanedStdOut()); - if (proc.result() == ProcessResult::FinishedWithSuccess) { + VcsOutputWindow::append(result.cleanedStdOut()); + if (result.result() == ProcessResult::FinishedWithSuccess) { resetCachedVcsInfo(workingDirectory); return true; - } else { - return false; } + return false; } /* Checkout, supports: @@ -1649,18 +1638,18 @@ bool GitClient::synchronousCheckoutFiles(const FilePath &workingDirectory, QStri if (revertStaging) arguments << revision; arguments << "--" << files; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, ShellCommand::ExpectRepoChanges); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - const QString fileArg = files.join(", "); - //: Meaning of the arguments: %1: revision, %2: files, %3: repository, - //: %4: Error message - msgCannotRun(tr("Cannot checkout \"%1\" of %2 in \"%3\": %4") - .arg(revision, fileArg, workingDirectory.toUserOutput(), proc.cleanedStdErr()), - errorMessage); - return false; - } - return true; + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, + ShellCommand::ExpectRepoChanges); + if (result.result() == ProcessResult::FinishedWithSuccess) + return true; + + const QString fileArg = files.join(", "); + //: Meaning of the arguments: %1: revision, %2: files, %3: repository, + //: %4: Error message + msgCannotRun(tr("Cannot checkout \"%1\" of %2 in \"%3\": %4") + .arg(revision, fileArg, workingDirectory.toUserOutput(), result.cleanedStdErr()), + errorMessage); + return false; } static inline QString msgParentRevisionFailed(const FilePath &workingDirectory, @@ -1701,13 +1690,12 @@ bool GitClient::synchronousRevListCmd(const FilePath &workingDirectory, const QS QString *output, QString *errorMessage) const { const QStringList arguments = QStringList({"rev-list", noColorOption}) + extraArguments; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, silentFlags); + if (result.result() != ProcessResult::FinishedWithSuccess) { + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), errorMessage); return false; } - *output = proc.cleanedStdOut(); + *output = result.cleanedStdOut(); return true; } @@ -1765,10 +1753,10 @@ QString GitClient::synchronousShortDescription(const FilePath &workingDirectory, QString GitClient::synchronousCurrentLocalBranch(const FilePath &workingDirectory) const { QString branch; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, {"symbolic-ref", HEAD}, silentFlags); - if (proc.result() == ProcessResult::FinishedWithSuccess) { - branch = proc.cleanedStdOut().trimmed(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, {"symbolic-ref", HEAD}, + silentFlags); + if (result.result() == ProcessResult::FinishedWithSuccess) { + branch = result.cleanedStdOut().trimmed(); } else { const QString gitDir = findGitDirForRepository(workingDirectory); const QString rebaseHead = gitDir + "/rebase-merge/head-name"; @@ -1783,21 +1771,20 @@ QString GitClient::synchronousCurrentLocalBranch(const FilePath &workingDirector return branch; } } - return QString(); + return {}; } bool GitClient::synchronousHeadRefs(const FilePath &workingDirectory, QStringList *output, QString *errorMessage) const { const QStringList arguments = {"show-ref", "--head", "--abbrev=10", "--dereference"}; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, silentFlags); + if (result.result() != ProcessResult::FinishedWithSuccess) { + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), errorMessage); return false; } - const QString stdOut = proc.cleanedStdOut(); + const QString stdOut = result.cleanedStdOut(); const QString headSha = stdOut.left(10); QString rest = stdOut.mid(15); @@ -1839,10 +1826,10 @@ QString GitClient::synchronousTopic(const FilePath &workingDirectory) const return remoteBranch; // No tag or remote branch - try git describe - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, QStringList{"describe"}, ShellCommand::NoOutput); - if (proc.result() == ProcessResult::FinishedWithSuccess) { - const QString stdOut = proc.cleanedStdOut().trimmed(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, QStringList{"describe"}, + ShellCommand::NoOutput); + if (result.result() == ProcessResult::FinishedWithSuccess) { + const QString stdOut = result.cleanedStdOut().trimmed(); if (!stdOut.isEmpty()) return stdOut; } @@ -1853,26 +1840,22 @@ bool GitClient::synchronousRevParseCmd(const FilePath &workingDirectory, const Q QString *output, QString *errorMessage) const { const QStringList arguments = {"rev-parse", ref}; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags); - *output = proc.cleanedStdOut().trimmed(); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage); - return false; - } - - return true; + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, silentFlags); + *output = result.cleanedStdOut().trimmed(); + if (result.result() == ProcessResult::FinishedWithSuccess) + return true; + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), errorMessage); + return false; } // Retrieve head revision QString GitClient::synchronousTopRevision(const FilePath &workingDirectory, QDateTime *dateTime) { const QStringList arguments = {"show", "-s", "--pretty=format:%H:%ct", HEAD}; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags); - if (proc.result() != ProcessResult::FinishedWithSuccess) + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, silentFlags); + if (result.result() != ProcessResult::FinishedWithSuccess) return QString(); - const QStringList output = proc.cleanedStdOut().trimmed().split(':'); + const QStringList output = result.cleanedStdOut().trimmed().split(':'); if (dateTime && output.size() > 1) { bool ok = false; const qint64 timeT = output.at(1).toLongLong(&ok); @@ -1883,16 +1866,16 @@ QString GitClient::synchronousTopRevision(const FilePath &workingDirectory, QDat bool GitClient::isRemoteCommit(const FilePath &workingDirectory, const QString &commit) { - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, {"branch", "-r", "--contains", commit}, silentFlags); - return !proc.rawStdOut().isEmpty(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, + {"branch", "-r", "--contains", commit}, silentFlags); + return !result.rawStdOut().isEmpty(); } bool GitClient::isFastForwardMerge(const FilePath &workingDirectory, const QString &branch) { - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, {"merge-base", HEAD, branch}, silentFlags); - return proc.cleanedStdOut().trimmed() == synchronousTopRevision(workingDirectory); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, + {"merge-base", HEAD, branch}, silentFlags); + return result.cleanedStdOut().trimmed() == synchronousTopRevision(workingDirectory); } // Format an entry in a one-liner for selection list using git log. @@ -1901,14 +1884,13 @@ QString GitClient::synchronousShortDescription(const FilePath &workingDirectory, { const QStringList arguments = {"log", noColorOption, ("--pretty=format:" + format), "--max-count=1", revision}; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, silentFlags); + if (result.result() != ProcessResult::FinishedWithSuccess) { VcsOutputWindow::appendSilently(tr("Cannot describe revision \"%1\" in \"%2\": %3") - .arg(revision, workingDirectory.toUserOutput(), proc.cleanedStdErr())); + .arg(revision, workingDirectory.toUserOutput(), result.cleanedStdErr())); return revision; } - return stripLastNewline(proc.cleanedStdOut()); + return stripLastNewline(result.cleanedStdOut()); } // Create a default message to be used for describing stashes @@ -1982,14 +1964,11 @@ bool GitClient::executeSynchronousStash(const FilePath &workingDirectory, const unsigned flags = ShellCommand::ShowStdOut | ShellCommand::ExpectRepoChanges | ShellCommand::ShowSuccessMessage; - QtcProcess proc; - vcsSynchronousExec(proc, workingDirectory, arguments, flags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage); - return false; - } - - return true; + const CommandResult result = vcsSynchronousExec(workingDirectory, arguments, flags); + if (result.result() == ProcessResult::FinishedWithSuccess) + return true; + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), errorMessage); + return false; } // Resolve a stash name from message @@ -2022,42 +2001,36 @@ bool GitClient::synchronousBranchCmd(const FilePath &workingDirectory, QStringLi QString *output, QString *errorMessage) const { branchArgs.push_front("branch"); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, branchArgs); - *output = proc.cleanedStdOut(); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(branchArgs, workingDirectory, proc.cleanedStdErr(), errorMessage); - return false; - } - return true; + const CommandResult result = vcsFullySynchronousExec(workingDirectory, branchArgs); + *output = result.cleanedStdOut(); + if (result.result() == ProcessResult::FinishedWithSuccess) + return true; + msgCannotRun(branchArgs, workingDirectory, result.cleanedStdErr(), errorMessage); + return false; } bool GitClient::synchronousTagCmd(const FilePath &workingDirectory, QStringList tagArgs, QString *output, QString *errorMessage) const { tagArgs.push_front("tag"); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, tagArgs); - *output = proc.cleanedStdOut(); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(tagArgs, workingDirectory, proc.cleanedStdErr(), errorMessage); - return false; - } - return true; + const CommandResult result = vcsFullySynchronousExec(workingDirectory, tagArgs); + *output = result.cleanedStdOut(); + if (result.result() == ProcessResult::FinishedWithSuccess) + return true; + msgCannotRun(tagArgs, workingDirectory, result.cleanedStdErr(), errorMessage); + return false; } bool GitClient::synchronousForEachRefCmd(const FilePath &workingDirectory, QStringList args, QString *output, QString *errorMessage) const { args.push_front("for-each-ref"); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, args, silentFlags); - *output = proc.cleanedStdOut(); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(args, workingDirectory, proc.cleanedStdErr(), errorMessage); - return false; - } - return true; + const CommandResult result = vcsFullySynchronousExec(workingDirectory, args, silentFlags); + *output = result.cleanedStdOut(); + if (result.result() == ProcessResult::FinishedWithSuccess) + return true; + msgCannotRun(args, workingDirectory, result.cleanedStdErr(), errorMessage); + return false; } ShellCommand *GitClient::asyncForEachRefCmd(const FilePath &workingDirectory, QStringList args) const @@ -2070,18 +2043,16 @@ bool GitClient::synchronousRemoteCmd(const FilePath &workingDirectory, QStringLi QString *output, QString *errorMessage, bool silent) const { remoteArgs.push_front("remote"); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, remoteArgs, silent ? silentFlags : 0); - - const QString stdErr = proc.cleanedStdErr(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, remoteArgs, + silent ? silentFlags : 0); + const QString stdErr = result.cleanedStdErr(); *errorMessage = stdErr; - *output = proc.cleanedStdOut(); + *output = result.cleanedStdOut(); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(remoteArgs, workingDirectory, stdErr, errorMessage); - return false; - } - return true; + if (result.result() == ProcessResult::FinishedWithSuccess) + return true; + msgCannotRun(remoteArgs, workingDirectory, stdErr, errorMessage); + return false; } QMap<QString,QString> GitClient::synchronousRemotesList(const FilePath &workingDirectory, @@ -2114,15 +2085,15 @@ QStringList GitClient::synchronousSubmoduleStatus(const FilePath &workingDirecto QString *errorMessage) const { // get submodule status - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, {"submodule", "status"}, silentFlags); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, {"submodule", "status"}, + silentFlags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { + if (result.result() != ProcessResult::FinishedWithSuccess) { msgCannotRun(tr("Cannot retrieve submodule status of \"%1\": %2") - .arg(workingDirectory.toUserOutput(), proc.cleanedStdErr()), errorMessage); - return QStringList(); + .arg(workingDirectory.toUserOutput(), result.cleanedStdErr()), errorMessage); + return {}; } - return splitLines(proc.cleanedStdOut()); + return splitLines(result.cleanedStdOut()); } SubmoduleDataMap GitClient::submoduleList(const FilePath &workingDirectory) const @@ -2195,13 +2166,12 @@ QByteArray GitClient::synchronousShow(const FilePath &workingDirectory, const QS return {}; } const QStringList arguments = {"show", decorateOption, noColorOption, "--no-patch", id}; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, flags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), nullptr); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, flags); + if (result.result() != ProcessResult::FinishedWithSuccess) { + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), nullptr); return {}; } - return proc.rawStdOut(); + return result.rawStdOut(); } // Retrieve list of files to be cleaned @@ -2211,10 +2181,10 @@ bool GitClient::cleanList(const FilePath &workingDirectory, const QString &modul const FilePath directory = workingDirectory.pathAppended(modulePath); const QStringList arguments = {"clean", "--dry-run", flag}; - QtcProcess proc; - vcsFullySynchronousExec(proc, directory, arguments, ShellCommand::ForceCLocale); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(arguments, directory, proc.cleanedStdErr(), errorMessage); + const CommandResult result = vcsFullySynchronousExec(directory, arguments, + ShellCommand::ForceCLocale); + if (result.result() != ProcessResult::FinishedWithSuccess) { + msgCannotRun(arguments, directory, result.cleanedStdErr(), errorMessage); return false; } @@ -2222,7 +2192,7 @@ bool GitClient::cleanList(const FilePath &workingDirectory, const QString &modul const QString relativeBase = modulePath.isEmpty() ? QString() : modulePath + '/'; const QString prefix = "Would remove "; const QStringList removeLines = Utils::filtered( - splitLines(proc.cleanedStdOut()), [](const QString &s) { + splitLines(result.cleanedStdOut()), [](const QString &s) { return s.startsWith("Would remove "); }); *files = Utils::transform(removeLines, [&relativeBase, &prefix](const QString &s) -> QString { @@ -2258,19 +2228,18 @@ bool GitClient::synchronousApplyPatch(const FilePath &workingDirectory, QStringList arguments = {"apply", "--whitespace=fix"}; arguments << extraArguments << file; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments); - const QString stdErr = proc.cleanedStdErr(); - if (proc.result() == ProcessResult::FinishedWithSuccess) { + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments); + const QString stdErr = result.cleanedStdErr(); + if (result.result() == ProcessResult::FinishedWithSuccess) { if (!stdErr.isEmpty()) *errorMessage = tr("There were warnings while applying \"%1\" to \"%2\":\n%3") .arg(file, workingDirectory.toUserOutput(), stdErr); return true; - } else { - *errorMessage = tr("Cannot apply patch \"%1\" to \"%2\": %3") - .arg(QDir::toNativeSeparators(file), workingDirectory.toUserOutput(), stdErr); - return false; } + + *errorMessage = tr("Cannot apply patch \"%1\" to \"%2\": %3") + .arg(QDir::toNativeSeparators(file), workingDirectory.toUserOutput(), stdErr); + return false; } Environment GitClient::processEnvironment() const @@ -2395,19 +2364,18 @@ GitClient::StatusResult GitClient::gitStatus(const FilePath &workingDirectory, S arguments << "--ignore-submodules=all"; arguments << "--porcelain" << "-b"; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags); - const QString stdOut = proc.cleanedStdOut(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, silentFlags); + const QString stdOut = result.cleanedStdOut(); if (output) *output = stdOut; - const bool statusRc = proc.result() == ProcessResult::FinishedWithSuccess; + const bool statusRc = result.result() == ProcessResult::FinishedWithSuccess; const bool branchKnown = !stdOut.startsWith("## HEAD (no branch)\n"); // Is it something really fatal? if (!statusRc && !branchKnown) { if (errorMessage) { - *errorMessage = tr("Cannot obtain status: %1").arg(proc.cleanedStdErr()); + *errorMessage = tr("Cannot obtain status: %1").arg(result.cleanedStdErr()); } return StatusFailed; } @@ -2541,16 +2509,15 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR const unsigned flags = ShellCommand::SshPasswordPrompt | ShellCommand::SuppressStdErr | ShellCommand::SuppressFailMessage; - QtcProcess proc; - vcsSynchronousExec(proc, - workingDirectory, {"ls-remote", repositoryURL, HEAD, "refs/heads/*"}, flags); + const CommandResult result = vcsSynchronousExec(workingDirectory, + {"ls-remote", repositoryURL, HEAD, "refs/heads/*"}, flags); QStringList branches; branches << tr("<Detached HEAD>"); QString headSha; // split "82bfad2f51d34e98b18982211c82220b8db049b<tab>refs/heads/master" bool headFound = false; bool branchFound = false; - const QStringList lines = proc.cleanedStdOut().split('\n'); + const QStringList lines = result.cleanedStdOut().split('\n'); for (const QString &line : lines) { if (line.endsWith("\tHEAD")) { QTC_CHECK(headSha.isNull()); @@ -2768,10 +2735,9 @@ bool GitClient::readDataFromCommit(const FilePath &repoDirectory, const QString { // Get commit data as "SHA1<lf>author<lf>email<lf>message". const QStringList arguments = {"log", "--max-count=1", "--pretty=format:%h\n%an\n%ae\n%B", commit}; - QtcProcess proc; - vcsFullySynchronousExec(proc, repoDirectory, arguments, silentFlags); + const CommandResult result = vcsFullySynchronousExec(repoDirectory, arguments, silentFlags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { + if (result.result() != ProcessResult::FinishedWithSuccess) { if (errorMessage) { *errorMessage = tr("Cannot retrieve last commit data of repository \"%1\".") .arg(repoDirectory.toUserOutput()); @@ -2782,7 +2748,7 @@ bool GitClient::readDataFromCommit(const FilePath &repoDirectory, const QString QTextCodec *authorCodec = HostOsInfo::isWindowsHost() ? QTextCodec::codecForName("UTF-8") : commitData.commitEncoding; - QByteArray stdOut = proc.rawStdOut(); + QByteArray stdOut = result.rawStdOut(); commitData.amendSHA1 = QLatin1String(shiftLogLine(stdOut)); commitData.panelData.author = authorCodec->toUnicode(shiftLogLine(stdOut)); commitData.panelData.email = authorCodec->toUnicode(shiftLogLine(stdOut)); @@ -3025,16 +2991,15 @@ bool GitClient::addAndCommit(const FilePath &repositoryDirectory, arguments << "--signoff"; } - QtcProcess proc; - vcsSynchronousExec(proc, repositoryDirectory, arguments, ShellCommand::NoFullySync); - if (proc.result() == ProcessResult::FinishedWithSuccess) { + const CommandResult result = vcsSynchronousExec(repositoryDirectory, arguments, + ShellCommand::NoFullySync); + if (result.result() == ProcessResult::FinishedWithSuccess) { VcsOutputWindow::appendMessage(msgCommitted(amendSHA1, commitCount)); GitPlugin::updateCurrentBranch(); return true; - } else { - VcsOutputWindow::appendError(tr("Cannot commit %n files\n", nullptr, commitCount)); - return false; } + VcsOutputWindow::appendError(tr("Cannot commit %n files\n", nullptr, commitCount)); + return false; } /* Revert: This function can be called with a file list (to revert single @@ -3167,11 +3132,10 @@ bool GitClient::executeAndHandleConflicts(const FilePath &workingDirectory, | ShellCommand::ShowStdOut | ShellCommand::ExpectRepoChanges | ShellCommand::ShowSuccessMessage; - QtcProcess proc; - vcsSynchronousExec(proc, workingDirectory, arguments, flags); + const CommandResult result = vcsSynchronousExec(workingDirectory, arguments, flags); // Notify about changed files or abort the rebase. - ConflictHandler::handleResponse(proc, workingDirectory, abortCommand); - return proc.result() == ProcessResult::FinishedWithSuccess; + ConflictHandler::handleResponse(result, workingDirectory, abortCommand); + return result.result() == ProcessResult::FinishedWithSuccess; } void GitClient::pull(const FilePath &workingDirectory, bool rebase) @@ -3202,10 +3166,9 @@ void GitClient::synchronousAbortCommand(const FilePath &workingDir, const QStrin return; } - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDir, {abortCommand, "--abort"}, + const CommandResult result = vcsFullySynchronousExec(workingDir, {abortCommand, "--abort"}, ShellCommand::ExpectRepoChanges | ShellCommand::ShowSuccessMessage); - VcsOutputWindow::append(proc.cleanedStdOut()); + VcsOutputWindow::append(result.cleanedStdOut()); } QString GitClient::synchronousTrackingBranch(const FilePath &workingDirectory, const QString &branch) @@ -3228,10 +3191,9 @@ QString GitClient::synchronousTrackingBranch(const FilePath &workingDirectory, c bool GitClient::synchronousSetTrackingBranch(const FilePath &workingDirectory, const QString &branch, const QString &tracking) { - QtcProcess proc; - vcsFullySynchronousExec(proc, - workingDirectory, {"branch", "--set-upstream-to=" + tracking, branch}); - return proc.result() == ProcessResult::FinishedWithSuccess; + const CommandResult result = vcsFullySynchronousExec(workingDirectory, + {"branch", "--set-upstream-to=" + tracking, branch}); + return result.result() == ProcessResult::FinishedWithSuccess; } ShellCommand *GitClient::asyncUpstreamStatus(const FilePath &workingDirectory, @@ -3302,8 +3264,7 @@ void GitClient::synchronousSubversionFetch(const FilePath &workingDirectory) con const unsigned flags = ShellCommand::SshPasswordPrompt | ShellCommand::ShowStdOut | ShellCommand::ShowSuccessMessage; - QtcProcess proc; - vcsSynchronousExec(proc, workingDirectory, {"svn", "fetch"}, flags); + vcsSynchronousExec(workingDirectory, {"svn", "fetch"}, flags); } void GitClient::subversionLog(const FilePath &workingDirectory) const @@ -3556,17 +3517,15 @@ bool GitClient::synchronousStashRemove(const FilePath &workingDirectory, const Q else arguments << "drop" << stash; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments); - if (proc.result() == ProcessResult::FinishedWithSuccess) { - const QString output = proc.cleanedStdOut(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments); + if (result.result() == ProcessResult::FinishedWithSuccess) { + const QString output = result.cleanedStdOut(); if (!output.isEmpty()) VcsOutputWindow::append(output); return true; - } else { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage); - return false; } + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), errorMessage); + return false; } bool GitClient::synchronousStashList(const FilePath &workingDirectory, QList<Stash> *stashes, @@ -3575,14 +3534,14 @@ bool GitClient::synchronousStashList(const FilePath &workingDirectory, QList<Sta stashes->clear(); const QStringList arguments = {"stash", "list", noColorOption}; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, ShellCommand::ForceCLocale); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(arguments, workingDirectory, proc.cleanedStdErr(), errorMessage); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, + ShellCommand::ForceCLocale); + if (result.result() != ProcessResult::FinishedWithSuccess) { + msgCannotRun(arguments, workingDirectory, result.cleanedStdErr(), errorMessage); return false; } Stash stash; - const QStringList lines = splitLines(proc.cleanedStdOut()); + const QStringList lines = splitLines(result.cleanedStdOut()); for (const QString &line : lines) { if (stash.parseStashLine(line)) stashes->push_back(stash); @@ -3615,11 +3574,11 @@ QString GitClient::readOneLine(const FilePath &workingDirectory, const QStringLi ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale(); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments, silentFlags, vcsTimeoutS(), codec); - if (proc.result() != ProcessResult::FinishedWithSuccess) - return QString(); - return proc.cleanedStdOut().trimmed(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, arguments, silentFlags, + vcsTimeoutS(), codec); + if (result.result() == ProcessResult::FinishedWithSuccess) + return result.cleanedStdOut().trimmed(); + return {}; } static unsigned parseGitVersion(const QString &output) diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 00408799db..7bf8c8dfeb 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -33,11 +33,11 @@ #include <vcsbase/vcsbaseconstants.h> #include <utils/algorithm.h> +#include <utils/commandline.h> #include <utils/fancylineedit.h> #include <utils/filesearch.h> #include <utils/fileutils.h> #include <utils/qtcassert.h> -#include <utils/qtcprocess.h> #include <utils/runextensions.h> #include <utils/shellcommand.h> #include <utils/textfileformat.h> @@ -198,10 +198,8 @@ public: QObject::connect(m_command.get(), &ShellCommand::stdOutText, [this, &fi](const QString &text) { read(fi, text); }); - QtcProcess proc; - proc.setTimeoutS(0); - m_command->runCommand(proc, {m_vcsBinary, arguments}); - switch (proc.result()) { + const CommandResult result = m_command->runCommand({m_vcsBinary, arguments}, {}, 0); + switch (result.result()) { case ProcessResult::TerminatedAbnormally: case ProcessResult::StartFailed: case ProcessResult::Hang: diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 1d28bd8249..587ffb791c 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -34,11 +34,11 @@ #include <vcsbase/vcsbaseeditorconfig.h> #include <vcsbase/vcsbasediffeditorcontroller.h> +#include <utils/commandline.h> #include <utils/environment.h> #include <utils/fileutils.h> #include <utils/hostosinfo.h> #include <utils/qtcassert.h> -#include <utils/qtcprocess.h> #include <utils/shellcommand.h> #include <QDateTime> @@ -96,13 +96,12 @@ bool MercurialClient::manifestSync(const FilePath &repository, const QString &re // This only works when called from the repo and outputs paths relative to it. const QStringList args(QLatin1String("manifest")); - QtcProcess proc; - vcsFullySynchronousExec(proc, repository, args); + const CommandResult result = vcsFullySynchronousExec(repository, args); const QDir repositoryDir(repository.toString()); const QFileInfo needle = QFileInfo(repositoryDir, relativeFilename); - const QStringList files = proc.cleanedStdOut().split(QLatin1Char('\n')); + const QStringList files = result.cleanedStdOut().split(QLatin1Char('\n')); for (const QString &fileName : files) { const QFileInfo managedFile(repositoryDir, fileName); if (needle == managedFile) @@ -126,18 +125,18 @@ bool MercurialClient::synchronousClone(const FilePath &workingDirectory, if (workingDirectory.exists()) { // Let's make first init QStringList arguments(QLatin1String("init")); - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, arguments); - if (proc.result() != ProcessResult::FinishedWithSuccess) + if (vcsFullySynchronousExec(workingDirectory, arguments).result() + != ProcessResult::FinishedWithSuccess) { return false; + } // Then pull remote repository arguments.clear(); arguments << QLatin1String("pull") << dstLocation; - QtcProcess proc1; - vcsSynchronousExec(proc1, workingDirectory, arguments, flags); - if (proc1.result() != ProcessResult::FinishedWithSuccess) + if (vcsSynchronousExec(workingDirectory, arguments, flags).result() + != ProcessResult::FinishedWithSuccess) { return false; + } // By now, there is no hgrc file -> create it FileSaver saver(workingDirectory.pathAppended(".hg/hgrc")); @@ -151,15 +150,13 @@ bool MercurialClient::synchronousClone(const FilePath &workingDirectory, // And last update repository arguments.clear(); arguments << QLatin1String("update"); - QtcProcess proc2; - vcsSynchronousExec(proc2, workingDirectory, arguments, flags); - return proc2.result() == ProcessResult::FinishedWithSuccess; + return vcsSynchronousExec(workingDirectory, arguments, flags).result() + == ProcessResult::FinishedWithSuccess; } else { QStringList arguments(QLatin1String("clone")); arguments << dstLocation << workingDirectory.parentDir().toString(); - QtcProcess proc; - vcsSynchronousExec(proc, workingDirectory.parentDir(), arguments, flags); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsSynchronousExec(workingDirectory.parentDir(), arguments, flags).result() + == ProcessResult::FinishedWithSuccess; } } @@ -175,18 +172,14 @@ bool MercurialClient::synchronousPull(const FilePath &workingDir, const QString // cause mercurial doesn`t understand LANG Environment env = Environment::systemEnvironment(); env.set("LANGUAGE", "C"); - QtcProcess proc; - proc.setTimeoutS(vcsTimeoutS()); ShellCommand *command = VcsBaseClient::createVcsCommand(workingDir, env); command->addFlags(flags); - command->runCommand(proc, {vcsBinary(), args}); + const CommandResult result = command->runCommand({vcsBinary(), args}, workingDir, vcsTimeoutS()); delete command; - const bool ok = proc.result() == ProcessResult::FinishedWithSuccess; - - parsePullOutput(proc.cleanedStdOut().trimmed()); - return ok; + parsePullOutput(result.cleanedStdOut().trimmed()); + return result.result() == ProcessResult::FinishedWithSuccess; } QString MercurialClient::branchQuerySync(const QString &repositoryRoot) @@ -222,26 +215,25 @@ QStringList MercurialClient::parentRevisionsSync(const FilePath &workingDirector args << QLatin1String("parents") << QLatin1String("-r") <<revision; if (!file.isEmpty()) args << file; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, args); - if (proc.result() != ProcessResult::FinishedWithSuccess) - return QStringList(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, args); + if (result.result() != ProcessResult::FinishedWithSuccess) + return {}; /* Looks like: \code changeset: 0:031a48610fba user: ... \endcode */ // Obtain first line and split by blank-delimited tokens - const QStringList lines = proc.cleanedStdOut().split(QLatin1Char('\n')); + const QStringList lines = result.cleanedStdOut().split(QLatin1Char('\n')); if (lines.size() < 1) { - VcsOutputWindow::appendSilently( - msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(proc.cleanedStdOut()))); - return QStringList(); + VcsOutputWindow::appendSilently(msgParentRevisionFailed(workingDirectory, revision, + msgParseParentsOutputFailed(result.cleanedStdOut()))); + return {}; } QStringList changeSets = lines.front().simplified().split(QLatin1Char(' ')); if (changeSets.size() < 2) { - VcsOutputWindow::appendSilently( - msgParentRevisionFailed(workingDirectory, revision, msgParseParentsOutputFailed(proc.cleanedStdOut()))); - return QStringList(); + VcsOutputWindow::appendSilently(msgParentRevisionFailed(workingDirectory, revision, + msgParseParentsOutputFailed(result.cleanedStdOut()))); + return {}; } // Remove revision numbers const QChar colon = QLatin1Char(':'); @@ -265,11 +257,10 @@ QString MercurialClient::shortDescriptionSync(const FilePath &workingDirectory, if (!format.isEmpty()) args << QLatin1String("--template") << format; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, args); - if (proc.result() != ProcessResult::FinishedWithSuccess) + const CommandResult result = vcsFullySynchronousExec(workingDirectory, args); + if (result.result() != ProcessResult::FinishedWithSuccess) return revision; - return stripLastNewline(proc.cleanedStdOut()); + return stripLastNewline(result.cleanedStdOut()); } // Default format: "SHA1 (author summmary)" @@ -285,9 +276,8 @@ bool MercurialClient::managesFile(const FilePath &workingDirectory, const QStrin { QStringList args; args << QLatin1String("status") << QLatin1String("--unknown") << fileName; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, args); - return proc.cleanedStdOut().isEmpty(); + const CommandResult result = vcsFullySynchronousExec(workingDirectory, args); + return result.cleanedStdOut().isEmpty(); } void MercurialClient::incoming(const FilePath &repositoryRoot, const QString &repository) diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp index 93b92de83e..511f3ea757 100644 --- a/src/plugins/subversion/subversionclient.cpp +++ b/src/plugins/subversion/subversionclient.cpp @@ -39,10 +39,10 @@ #include <diffeditor/diffutils.h> #include <utils/algorithm.h> +#include <utils/commandline.h> #include <utils/environment.h> #include <utils/hostosinfo.h> #include <utils/qtcassert.h> -#include <utils/qtcprocess.h> #include <utils/shellcommand.h> #include <QDir> @@ -83,18 +83,19 @@ bool SubversionClient::doCommit(const FilePath &repositoryRoot, const QString &commitMessageFile, const QStringList &extraOptions) const { - const QStringList svnExtraOptions = - QStringList(extraOptions) - << SubversionClient::addAuthenticationOptions(static_cast<SubversionSettings &>(settings())) - << QLatin1String(Constants::NON_INTERACTIVE_OPTION) - << QLatin1String("--encoding") << QLatin1String("UTF-8") - << QLatin1String("--file") << commitMessageFile; - - QStringList args(vcsCommandString(CommitCommand)); - QtcProcess proc; - vcsSynchronousExec(proc, repositoryRoot, args << svnExtraOptions << escapeFiles(files), + QStringList args; + args << vcsCommandString(CommitCommand) + << extraOptions + << SubversionClient::addAuthenticationOptions(static_cast<SubversionSettings &>(settings())) + << QLatin1String(Constants::NON_INTERACTIVE_OPTION) + << QLatin1String("--encoding") + << QLatin1String("UTF-8") + << QLatin1String("--file") + << commitMessageFile + << escapeFiles(files); + const CommandResult result = vcsSynchronousExec(repositoryRoot, args, ShellCommand::ShowStdOut | ShellCommand::NoFullySync); - return proc.result() == ProcessResult::FinishedWithSuccess; + return result.result() == ProcessResult::FinishedWithSuccess; } void SubversionClient::commit(const FilePath &repositoryRoot, @@ -151,12 +152,11 @@ QString SubversionClient::synchronousTopic(const FilePath &repository) const else svnVersionBinary = svnVersionBinary.left(pos + 1); svnVersionBinary.append(HostOsInfo::withExecutableSuffix("svnversion")); - QtcProcess proc; - vcsFullySynchronousExec(proc, repository, {FilePath::fromString(svnVersionBinary), args}); - if (proc.result() != ProcessResult::FinishedWithSuccess) - return QString(); - - return proc.cleanedStdOut().trimmed(); + const CommandResult result = vcsFullySynchronousExec(repository, + {FilePath::fromString(svnVersionBinary), args}); + if (result.result() == ProcessResult::FinishedWithSuccess) + return result.cleanedStdOut().trimmed(); + return {}; } QString SubversionClient::escapeFile(const QString &file) diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 4a96899644..4d2a6492a6 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -51,12 +51,12 @@ #include <coreplugin/messagemanager.h> #include <utils/algorithm.h> +#include <utils/commandline.h> #include <utils/environment.h> #include <utils/fileutils.h> #include <utils/hostosinfo.h> #include <utils/parameteraction.h> #include <utils/qtcassert.h> -#include <utils/qtcprocess.h> #include <utils/shellcommand.h> #include <utils/stringutils.h> @@ -1019,16 +1019,14 @@ SubversionResponse SubversionPluginPrivate::runSvn(const FilePath &workingDir, return response; } - QtcProcess proc; - m_client->vcsFullySynchronousExec(proc, workingDir, arguments, flags, - m_settings.timeout.value() * defaultTimeoutMutiplier, - outputCodec); + const CommandResult result = m_client->vcsFullySynchronousExec(workingDir, arguments, flags, + m_settings.timeout.value() * defaultTimeoutMutiplier, outputCodec); - response.error = proc.result() != ProcessResult::FinishedWithSuccess; + response.error = result.result() != ProcessResult::FinishedWithSuccess; if (response.error) - response.message = proc.exitMessage(); - response.stdErr = proc.cleanedStdErr(); - response.stdOut = proc.cleanedStdOut(); + response.message = result.exitMessage(); + response.stdErr = result.cleanedStdErr(); + response.stdOut = result.cleanedStdOut(); return response; } diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index 5a927df86a..1d62785ed9 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -35,10 +35,10 @@ #include <coreplugin/idocument.h> #include <coreplugin/progressmanager/progressmanager.h> +#include <utils/commandline.h> #include <utils/environment.h> #include <utils/globalfilechangeblocker.h> #include <utils/qtcassert.h> -#include <utils/qtcprocess.h> #include <utils/shellcommand.h> #include <vcsbase/vcsbaseeditor.h> @@ -240,24 +240,21 @@ QString VcsBaseClientImpl::stripLastNewline(const QString &in) return in; } -void VcsBaseClientImpl::vcsFullySynchronousExec(QtcProcess &proc, - const FilePath &workingDir, const QStringList &args, - unsigned flags, int timeoutS, QTextCodec *codec) const +CommandResult VcsBaseClientImpl::vcsFullySynchronousExec(const FilePath &workingDir, + const QStringList &args, unsigned flags, int timeoutS, QTextCodec *codec) const { - vcsFullySynchronousExec(proc, workingDir, {vcsBinary(), args}, flags, timeoutS, codec); + return vcsFullySynchronousExec(workingDir, {vcsBinary(), args}, flags, timeoutS, codec); } -void VcsBaseClientImpl::vcsFullySynchronousExec(QtcProcess &proc, - const FilePath &workingDir, const CommandLine &cmdLine, - unsigned flags, int timeoutS, QTextCodec *codec) const +CommandResult VcsBaseClientImpl::vcsFullySynchronousExec(const FilePath &workingDir, + const CommandLine &cmdLine, unsigned flags, int timeoutS, QTextCodec *codec) const { ShellCommand command(workingDir, processEnvironment()); new VcsCommandDecorator(&command); command.addFlags(flags); if (codec) command.setCodec(codec); - proc.setTimeoutS(timeoutS > 0 ? timeoutS : vcsTimeoutS()); - command.runCommand(proc, cmdLine); + return command.runCommand(cmdLine, workingDir, timeoutS > 0 ? timeoutS : vcsTimeoutS()); } void VcsBaseClientImpl::resetCachedVcsInfo(const FilePath &workingDir) @@ -293,19 +290,17 @@ ShellCommand *VcsBaseClientImpl::vcsExec(const FilePath &workingDirectory, return command; } -void VcsBaseClientImpl::vcsSynchronousExec(QtcProcess &proc, - const FilePath &workingDir, - const QStringList &args, - unsigned flags, - QTextCodec *outputCodec) const +CommandResult VcsBaseClientImpl::vcsSynchronousExec(const FilePath &workingDir, + const QStringList &args, + unsigned flags, + QTextCodec *outputCodec) const { Environment env = processEnvironment(); ShellCommand command(workingDir, env.isValid() ? env : Environment::systemEnvironment()); new VcsCommandDecorator(&command); - proc.setTimeoutS(vcsTimeoutS()); command.addFlags(flags); command.setCodec(outputCodec); - command.runCommand(proc, {vcsBinary(), args}); + return command.runCommand({vcsBinary(), args}, workingDir, vcsTimeoutS()); } int VcsBaseClientImpl::vcsTimeoutS() const @@ -367,11 +362,10 @@ bool VcsBaseClient::synchronousCreateRepository(const FilePath &workingDirectory { QStringList args(vcsCommandString(CreateRepositoryCommand)); args << extraOptions; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDirectory, args); - if (proc.result() != ProcessResult::FinishedWithSuccess) + const CommandResult result = vcsFullySynchronousExec(workingDirectory, args); + if (result.result() != ProcessResult::FinishedWithSuccess) return false; - VcsOutputWindow::append(proc.cleanedStdOut()); + VcsOutputWindow::append(result.cleanedStdOut()); resetCachedVcsInfo(workingDirectory); @@ -387,10 +381,9 @@ bool VcsBaseClient::synchronousClone(const FilePath &workingDir, args << vcsCommandString(CloneCommand) << extraOptions << srcLocation << dstLocation; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDir, args); + const CommandResult result = vcsFullySynchronousExec(workingDir, args); resetCachedVcsInfo(workingDir); - return proc.result() == ProcessResult::FinishedWithSuccess; + return result.result() == ProcessResult::FinishedWithSuccess; } bool VcsBaseClient::synchronousAdd(const FilePath &workingDir, @@ -399,9 +392,7 @@ bool VcsBaseClient::synchronousAdd(const FilePath &workingDir, { QStringList args; args << vcsCommandString(AddCommand) << extraOptions << relFileName; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDir, args); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsFullySynchronousExec(workingDir, args).result() == ProcessResult::FinishedWithSuccess; } bool VcsBaseClient::synchronousRemove(const FilePath &workingDir, @@ -410,9 +401,7 @@ bool VcsBaseClient::synchronousRemove(const FilePath &workingDir, { QStringList args; args << vcsCommandString(RemoveCommand) << extraOptions << filename; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDir, args); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsFullySynchronousExec(workingDir, args).result() == ProcessResult::FinishedWithSuccess; } bool VcsBaseClient::synchronousMove(const FilePath &workingDir, @@ -422,9 +411,7 @@ bool VcsBaseClient::synchronousMove(const FilePath &workingDir, { QStringList args; args << vcsCommandString(MoveCommand) << extraOptions << from << to; - QtcProcess proc; - vcsFullySynchronousExec(proc, workingDir, args); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsFullySynchronousExec(workingDir, args).result() == ProcessResult::FinishedWithSuccess; } bool VcsBaseClient::synchronousPull(const FilePath &workingDir, @@ -437,9 +424,8 @@ bool VcsBaseClient::synchronousPull(const FilePath &workingDir, const unsigned flags = ShellCommand::SshPasswordPrompt | ShellCommand::ShowStdOut | ShellCommand::ShowSuccessMessage; - QtcProcess proc; - vcsSynchronousExec(proc, workingDir, args, flags); - const bool ok = proc.result() == ProcessResult::FinishedWithSuccess; + const bool ok = vcsSynchronousExec(workingDir, args, flags).result() + == ProcessResult::FinishedWithSuccess; if (ok) emit changed(QVariant(workingDir.toString())); return ok; @@ -455,9 +441,8 @@ bool VcsBaseClient::synchronousPush(const FilePath &workingDir, const unsigned flags = ShellCommand::SshPasswordPrompt | ShellCommand::ShowStdOut | ShellCommand::ShowSuccessMessage; - QtcProcess proc; - vcsSynchronousExec(proc, workingDir, args, flags); - return proc.result() == ProcessResult::FinishedWithSuccess; + return vcsSynchronousExec(workingDir, args, flags).result() + == ProcessResult::FinishedWithSuccess; } VcsBaseEditorWidget *VcsBaseClient::annotate( diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h index 7a41fb4d26..0c503b112c 100644 --- a/src/plugins/vcsbase/vcsbaseclient.h +++ b/src/plugins/vcsbase/vcsbaseclient.h @@ -40,13 +40,12 @@ #include <functional> QT_BEGIN_NAMESPACE -class QFileInfo; class QTextCodec; class QToolBar; QT_END_NAMESPACE namespace Utils { -class QtcProcess; +class CommandResult; class ShellCommand; } @@ -109,12 +108,12 @@ public: static QString stripLastNewline(const QString &in); // Fully synchronous VCS execution (QProcess-based) - void vcsFullySynchronousExec(Utils::QtcProcess &process, - const Utils::FilePath &workingDir, const QStringList &args, - unsigned flags = 0, int timeoutS = -1, QTextCodec *codec = nullptr) const; - void vcsFullySynchronousExec(Utils::QtcProcess &process, - const Utils::FilePath &workingDir, const Utils::CommandLine &cmdLine, - unsigned flags = 0, int timeoutS = -1, QTextCodec *codec = nullptr) const; + Utils::CommandResult vcsFullySynchronousExec(const Utils::FilePath &workingDir, + const QStringList &args, unsigned flags = 0, + int timeoutS = -1, QTextCodec *codec = nullptr) const; + Utils::CommandResult vcsFullySynchronousExec(const Utils::FilePath &workingDir, + const Utils::CommandLine &cmdLine, unsigned flags = 0, + int timeoutS = -1, QTextCodec *codec = nullptr) const; // Simple helper to execute a single command using createCommand and enqueueJob. Utils::ShellCommand *vcsExec(const Utils::FilePath &workingDirectory, @@ -131,11 +130,10 @@ protected: // Synchronous VCS execution using Utils::SynchronousProcess, with // log windows updating (using VcsBasePlugin::runVcs with flags) - void vcsSynchronousExec(Utils::QtcProcess &proc, - const Utils::FilePath &workingDir, - const QStringList &args, - unsigned flags = 0, - QTextCodec *outputCodec = nullptr) const; + Utils::CommandResult vcsSynchronousExec(const Utils::FilePath &workingDir, + const QStringList &args, + unsigned flags = 0, + QTextCodec *outputCodec = nullptr) const; private: void saveSettings(); |