diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp index 3369c37d23b..47a58da50e5 100644 --- a/src/libs/utils/shellcommand.cpp +++ b/src/libs/utils/shellcommand.cpp @@ -205,15 +205,15 @@ void ShellCommand::addFlags(unsigned f) } void ShellCommand::addJob(const Utils::FileName &binary, const QStringList &arguments, - Utils::ExitCodeInterpreter *interpreter) + const QString &workingDirectory, Utils::ExitCodeInterpreter *interpreter) { - addJob(binary, arguments, defaultTimeoutS(), interpreter); + addJob(binary, arguments, defaultTimeoutS(), workingDirectory, interpreter); } void ShellCommand::addJob(const Utils::FileName &binary, const QStringList &arguments, int timeoutS, - Utils::ExitCodeInterpreter *interpreter) + const QString &workingDirectory, Utils::ExitCodeInterpreter *interpreter) { - d->m_jobs.push_back(Internal::ShellCommandPrivate::Job(d->m_defaultWorkingDirectory, binary, + d->m_jobs.push_back(Internal::ShellCommandPrivate::Job(workDirectory(workingDirectory), binary, arguments, timeoutS, interpreter)); } @@ -254,6 +254,13 @@ void ShellCommand::addTask(QFuture &future) Q_UNUSED(future); } +QString ShellCommand::workDirectory(const QString &wd) const +{ + if (!wd.isEmpty()) + return wd; + return defaultWorkingDirectory(); +} + bool ShellCommand::lastExecutionSuccess() const { return d->m_lastExecSuccess; @@ -282,7 +289,8 @@ void ShellCommand::run(QFutureInterface &future) for (int j = 0; j < count; j++) { const Internal::ShellCommandPrivate::Job &job = d->m_jobs.at(j); Utils::SynchronousProcessResponse resp - = runCommand(job.binary, job.arguments, job.timeoutS, job.exitCodeInterpreter); + = runCommand(job.binary, job.arguments, job.timeoutS, job.workingDirectory, + job.exitCodeInterpreter); stdOut += resp.stdOut; stdErr += resp.stdErr; d->m_lastExecExitCode = resp.exitCode; @@ -312,10 +320,13 @@ void ShellCommand::run(QFutureInterface &future) Utils::SynchronousProcessResponse ShellCommand::runCommand(const Utils::FileName &binary, const QStringList &arguments, int timeoutS, + const QString &workingDirectory, Utils::ExitCodeInterpreter *interpreter) { Utils::SynchronousProcessResponse response; + const QString dir = workDirectory(workingDirectory); + if (binary.isEmpty()) { response.result = Utils::SynchronousProcessResponse::StartFailed; return response; @@ -324,16 +335,15 @@ Utils::SynchronousProcessResponse ShellCommand::runCommand(const Utils::FileName QSharedPointer proxy(d->m_proxyFactory()); if (!(d->m_flags & SuppressCommandLogging)) - proxy->appendCommand(d->m_defaultWorkingDirectory, binary, arguments); + proxy->appendCommand(dir, binary, arguments); if (d->m_flags & FullySynchronously) { - response = runSynchronous(binary, arguments, timeoutS, interpreter); + response = runSynchronous(binary, arguments, timeoutS, dir, interpreter); } else { Utils::SynchronousProcess process; process.setExitCodeInterpreter(interpreter); connect(this, &ShellCommand::terminate, &process, &Utils::SynchronousProcess::terminate); - if (!d->m_defaultWorkingDirectory.isEmpty()) - process.setWorkingDirectory(d->m_defaultWorkingDirectory); + process.setWorkingDirectory(dir); process.setProcessEnvironment(processEnvironment()); process.setTimeoutS(timeoutS); @@ -398,6 +408,7 @@ Utils::SynchronousProcessResponse ShellCommand::runCommand(const Utils::FileName Utils::SynchronousProcessResponse ShellCommand::runSynchronous(const Utils::FileName &binary, const QStringList &arguments, int timeoutS, + const QString &workingDirectory, Utils::ExitCodeInterpreter *interpreter) { Utils::SynchronousProcessResponse response; @@ -407,7 +418,7 @@ Utils::SynchronousProcessResponse ShellCommand::runSynchronous(const Utils::File // Set up process QSharedPointer process = Utils::SynchronousProcess::createProcess(processFlags()); if (!d->m_defaultWorkingDirectory.isEmpty()) - process->setWorkingDirectory(d->m_defaultWorkingDirectory); + process->setWorkingDirectory(workDirectory(workingDirectory)); process->setProcessEnvironment(processEnvironment()); if (d->m_flags & MergeOutputChannels) process->setProcessChannelMode(QProcess::MergedChannels); @@ -460,17 +471,19 @@ Utils::SynchronousProcessResponse ShellCommand::runSynchronous(const Utils::File } bool ShellCommand::runFullySynchronous(const Utils::FileName &binary, const QStringList &arguments, - int timeoutS, QByteArray *outputData, QByteArray *errorData) + int timeoutS, QByteArray *outputData, QByteArray *errorData, + const QString &workingDirectory) { QTC_ASSERT(!binary.isEmpty(), return false); QScopedPointer proxy(d->m_proxyFactory()); + const QString dir = workDirectory(workingDirectory); if (!(d->m_flags & SuppressCommandLogging)) - proxy->appendCommand(d->m_defaultWorkingDirectory, binary, arguments); + proxy->appendCommand(dir, binary, arguments); QProcess process; - process.setWorkingDirectory(d->m_defaultWorkingDirectory); + process.setWorkingDirectory(dir); process.setProcessEnvironment(d->m_environment); process.start(binary.toString(), arguments); diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h index 45cbc5f3941..cd66d8838e5 100644 --- a/src/libs/utils/shellcommand.h +++ b/src/libs/utils/shellcommand.h @@ -115,14 +115,15 @@ public: ShellCommand(const QString &workingDirectory, const QProcessEnvironment &environment); - ~ShellCommand(); + ~ShellCommand() override; QString displayName() const; void setDisplayName(const QString &name); - void addJob(const FileName &binary, const QStringList &arguments, ExitCodeInterpreter *interpreter = 0); + void addJob(const FileName &binary, const QStringList &arguments, + const QString &workingDirectory = QString(), ExitCodeInterpreter *interpreter = 0); void addJob(const FileName &binary, const QStringList &arguments, int timeoutS, - ExitCodeInterpreter *interpreter = 0); + const QString &workingDirectory = QString(), ExitCodeInterpreter *interpreter = 0); void execute(); void abort(); bool lastExecutionSuccess() const; @@ -149,10 +150,13 @@ public: void setOutputProxyFactory(const std::function &factory); virtual SynchronousProcessResponse runCommand(const FileName &binary, const QStringList &arguments, - int timeoutS, ExitCodeInterpreter *interpreter = 0); + int timeoutS, + const QString &workingDirectory = QString(), + ExitCodeInterpreter *interpreter = 0); // Make sure to not pass through the event loop at all: virtual bool runFullySynchronous(const FileName &binary, const QStringList &arguments, - int timeoutS, QByteArray *outputData, QByteArray *errorData); + int timeoutS, QByteArray *outputData, QByteArray *errorData, + const QString &workingDirectory = QString()); public slots: void cancel(); @@ -168,11 +172,13 @@ signals: protected: virtual unsigned processFlags() const; virtual void addTask(QFuture &future); + QString workDirectory(const QString &wd) const; private: void run(QFutureInterface &future); SynchronousProcessResponse runSynchronous(const FileName &binary, const QStringList &arguments, - int timeoutS, ExitCodeInterpreter *interpreter = 0); + int timeoutS, const QString &workingDirectory, + ExitCodeInterpreter *interpreter = 0); class Internal::ShellCommandPrivate *const d; }; diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index 327d1dfa6ef..36df6fb2f00 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -155,9 +155,10 @@ VcsCommand *VcsBaseClientImpl::createCommand(const QString &workingDirectory, } void VcsBaseClientImpl::enqueueJob(VcsCommand *cmd, const QStringList &args, + const QString &workingDirectory, Utils::ExitCodeInterpreter *interpreter) { - cmd->addJob(vcsBinary(), args, vcsTimeoutS(), interpreter); + cmd->addJob(vcsBinary(), args, vcsTimeoutS(), workingDirectory, interpreter); cmd->execute(); } @@ -470,7 +471,7 @@ void VcsBaseClient::diff(const QString &workingDir, const QStringList &files, QTextCodec *codec = source.isEmpty() ? static_cast(0) : VcsBaseEditor::getCodec(source); VcsCommand *command = createCommand(workingDir, editor); command->setCodec(codec); - enqueueJob(command, args, exitCodeInterpreter(DiffCommand, command)); + enqueueJob(command, args, workingDir, exitCodeInterpreter(DiffCommand, command)); } void VcsBaseClient::log(const QString &workingDir, const QStringList &files, diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h index 8fdf6971f2c..f88b2440a04 100644 --- a/src/plugins/vcsbase/vcsbaseclient.h +++ b/src/plugins/vcsbase/vcsbaseclient.h @@ -91,6 +91,7 @@ public: JobOutputBindMode mode = NoOutputBind) const; void enqueueJob(VcsCommand *cmd, const QStringList &args, + const QString &workingDirectory = QString(), Utils::ExitCodeInterpreter *interpreter = 0); virtual QProcessEnvironment processEnvironment() const; diff --git a/src/plugins/vcsbase/vcscommand.cpp b/src/plugins/vcsbase/vcscommand.cpp index 578c911b80d..e888e96ca9c 100644 --- a/src/plugins/vcsbase/vcscommand.cpp +++ b/src/plugins/vcsbase/vcscommand.cpp @@ -93,30 +93,33 @@ const QProcessEnvironment VcsCommand::processEnvironment() const Utils::SynchronousProcessResponse VcsCommand::runCommand(const Utils::FileName &binary, const QStringList &arguments, int timeoutS, + const QString &workingDirectory, Utils::ExitCodeInterpreter *interpreter) { Utils::SynchronousProcessResponse response - = Core::ShellCommand::runCommand(binary, arguments, timeoutS, interpreter); - emitRepositoryChanged(); + = Core::ShellCommand::runCommand(binary, arguments, timeoutS, workingDirectory, + interpreter); + emitRepositoryChanged(workingDirectory); return response; } bool VcsCommand::runFullySynchronous(const Utils::FileName &binary, const QStringList &arguments, - int timeoutS, QByteArray *outputData, QByteArray *errorData) + int timeoutS, QByteArray *outputData, QByteArray *errorData, + const QString &workingDirectory) { bool result = Core::ShellCommand::runFullySynchronous(binary, arguments, timeoutS, - outputData, errorData); - emitRepositoryChanged(); + outputData, errorData, workingDirectory); + emitRepositoryChanged(workingDirectory); return result; } -void VcsCommand::emitRepositoryChanged() +void VcsCommand::emitRepositoryChanged(const QString &workingDirectory) { if (m_preventRepositoryChanged || !(flags() & VcsCommand::ExpectRepoChanges)) return; // TODO tell the document manager that the directory now received all expected changes // Core::DocumentManager::unexpectDirectoryChange(d->m_workingDirectory); - Core::VcsManager::emitRepositoryChanged(defaultWorkingDirectory()); + Core::VcsManager::emitRepositoryChanged(workDirectory(workingDirectory)); } unsigned VcsCommand::processFlags() const diff --git a/src/plugins/vcsbase/vcscommand.h b/src/plugins/vcsbase/vcscommand.h index e813e9c115e..e3e9053b6b0 100644 --- a/src/plugins/vcsbase/vcscommand.h +++ b/src/plugins/vcsbase/vcscommand.h @@ -53,13 +53,15 @@ public: Utils::SynchronousProcessResponse runCommand(const Utils::FileName &binary, const QStringList &arguments, int timeoutS, + const QString &workDirectory = QString(), Utils::ExitCodeInterpreter *interpreter = 0); bool runFullySynchronous(const Utils::FileName &binary, const QStringList &arguments, - int timeoutS, QByteArray *outputData, QByteArray *errorData); + int timeoutS, QByteArray *outputData, QByteArray *errorData, + const QString &workingDirectory = QString()); private: unsigned processFlags() const; - void emitRepositoryChanged(); + void emitRepositoryChanged(const QString &workingDirectory); void coreAboutToClose();