diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index e7407821d22d58a7bb0fd1826fd664e46028f0a4..9325dc88b6e5d5dc336b11d17c7d76de363eb68b 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -934,13 +934,13 @@ bool PerforcePlugin::vcsMove(const QString &workingDir, const QString &from, con QStringList args; args << QLatin1String("edit") << from; const PerforceResponse editResult = runP4Cmd(workingDir, args, - CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow); + RunFullySynchronous|CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow); if (editResult.error) return false; args.clear(); args << QLatin1String("move") << from << to; const PerforceResponse moveResult = runP4Cmd(workingDir, args, - CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow); + RunFullySynchronous|CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow); return !moveResult.error; } diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index c3a1f9f5bc9a35895b5f495103c988b96eae50e9..f556bba30813c18f35e5d9e8c9c761fa02a5a2cf 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -1219,11 +1219,9 @@ bool SubversionPlugin::vcsMove(const QString &workingDir, const QString &from, c { QStringList args(QLatin1String("move")); args << QDir::toNativeSeparators(from) << QDir::toNativeSeparators(to); - qDebug()<<args; const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), - SshPasswordPrompt|ShowStdOutInLogWindow); - qDebug() << response.stdOut << "\n"<<response.stdErr; + SshPasswordPrompt|ShowStdOutInLogWindow|FullySynchronously); return !response.error; } diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 14b395f5873c9953f4803c66560b27cee80e3849..9d7b2b5310dd54327fec88af6755a8c3697c55fd 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -50,6 +50,7 @@ #include <QtCore/QDir> #include <QtCore/QSharedData> #include <QtCore/QScopedPointer> +#include <QtCore/QSharedPointer> #include <QtCore/QProcessEnvironment> #include <QtCore/QTextStream> #include <QtCore/QTextCodec> @@ -701,6 +702,72 @@ void VCSBasePlugin::setProcessEnvironment(QProcessEnvironment *e, bool forceCLoc e->insert(QLatin1String("SSH_ASKPASS"), sshPromptBinary); } +// Run a process fully synchronously, returning Utils::SynchronousProcessResponse +// response struct and using the VCSBasePlugin flags as applicable +static Utils::SynchronousProcessResponse + runVCS_FullySynchronously(const QString &workingDir, + const QString &binary, + const QStringList &arguments, + int timeOutMS, + QProcessEnvironment env, + unsigned flags, + QTextCodec *outputCodec = 0) +{ + VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance(); + + // Set up process + unsigned processFlags = 0; + if (VCSBasePlugin::isSshPromptConfigured() && (flags & VCSBasePlugin::SshPasswordPrompt)) + processFlags |= Utils::SynchronousProcess::UnixTerminalDisabled; + QSharedPointer<QProcess> process = Utils::SynchronousProcess::createProcess(processFlags); + if (!workingDir.isEmpty()) + process->setWorkingDirectory(workingDir); + process->setProcessEnvironment(env); + if (flags & VCSBasePlugin::MergeOutputChannels) + process->setProcessChannelMode(QProcess::MergedChannels); + + // Start + process->start(binary, arguments); + Utils::SynchronousProcessResponse response; + if (!process->waitForStarted()) { + response.result = Utils::SynchronousProcessResponse::StartFailed; + return response; + } + + // process output + QByteArray stdOut; + QByteArray stdErr; + const bool timedOut = + !Utils::SynchronousProcess::readDataFromProcess(*process.data(), timeOutMS, + &stdOut, &stdErr, true); + + if (!stdErr.isEmpty()) { + response.stdErr = QString::fromLocal8Bit(stdErr).remove('\r'); + if (!(flags & VCSBasePlugin::SuppressStdErrInLogWindow)) + outputWindow->append(response.stdErr); + } + + if (!stdOut.isEmpty()) { + response.stdOut = (outputCodec ? outputCodec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut)) + .remove('\r'); + if (flags & VCSBasePlugin::ShowStdOutInLogWindow) + outputWindow->append(response.stdOut); + } + + // Result + if (timedOut) { + response.result = Utils::SynchronousProcessResponse::Hang; + } else if (process->exitStatus() != QProcess::NormalExit) { + response.result = Utils::SynchronousProcessResponse::TerminatedAbnormally; + } else { + response.result = process->exitCode() == 0 ? + Utils::SynchronousProcessResponse::Finished : + Utils::SynchronousProcessResponse::FinishedError; + } + return response; +} + + Utils::SynchronousProcessResponse VCSBasePlugin::runVCS(const QString &workingDir, const QString &binary, @@ -747,56 +814,66 @@ Utils::SynchronousProcessResponse nsp << "suppress_log"; if (flags & ForceCLocale) nsp << "c_locale"; + if (flags & FullySynchronously) + nsp << "fully_synchronously"; if (outputCodec) nsp << " Codec: " << outputCodec->name(); } - // Run, connect stderr to the output window - Utils::SynchronousProcess process; - if (!workingDir.isEmpty()) - process.setWorkingDirectory(workingDir); - VCSBase::VCSBasePlugin::setProcessEnvironment(&env, (flags & ForceCLocale)); - process.setProcessEnvironment(env); - process.setTimeout(timeOutMS); - if (outputCodec) - process.setStdOutCodec(outputCodec); - - // Suppress terminal on UNIX for ssh prompts if it is configured. - if (sshPromptConfigured && (flags & SshPasswordPrompt)) - process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled); - - // connect stderr to the output window if desired - if (flags & MergeOutputChannels) { - process.setProcessChannelMode(QProcess::MergedChannels); + + Utils::SynchronousProcessResponse response; + + if (flags & FullySynchronously) { + response = runVCS_FullySynchronously(workingDir, binary, arguments, timeOutMS, + env, flags, outputCodec); } else { - if (!(flags & SuppressStdErrInLogWindow)) { - process.setStdErrBufferedSignalsEnabled(true); - connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString))); + // Run, connect stderr to the output window + Utils::SynchronousProcess process; + if (!workingDir.isEmpty()) + process.setWorkingDirectory(workingDir); + + process.setProcessEnvironment(env); + process.setTimeout(timeOutMS); + if (outputCodec) + process.setStdOutCodec(outputCodec); + + // Suppress terminal on UNIX for ssh prompts if it is configured. + if (sshPromptConfigured && (flags & SshPasswordPrompt)) + process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled); + + // connect stderr to the output window if desired + if (flags & MergeOutputChannels) { + process.setProcessChannelMode(QProcess::MergedChannels); + } else { + if (!(flags & SuppressStdErrInLogWindow)) { + process.setStdErrBufferedSignalsEnabled(true); + connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString))); + } } - } - // connect stdout to the output window if desired - if (flags & ShowStdOutInLogWindow) { - process.setStdOutBufferedSignalsEnabled(true); - connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString))); - } + // connect stdout to the output window if desired + if (flags & ShowStdOutInLogWindow) { + process.setStdOutBufferedSignalsEnabled(true); + connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString))); + } - process.setTimeOutMessageBoxEnabled(true); + process.setTimeOutMessageBoxEnabled(true); - // Run! - const Utils::SynchronousProcessResponse sp_resp = process.run(binary, arguments); + // Run! + response = process.run(binary, arguments); + } // Success/Fail message in appropriate window? - if (sp_resp.result == Utils::SynchronousProcessResponse::Finished) { + if (response.result == Utils::SynchronousProcessResponse::Finished) { if (flags & ShowSuccessMessage) - outputWindow->append(sp_resp.exitMessage(binary, timeOutMS)); + outputWindow->append(response.exitMessage(binary, timeOutMS)); } else { if (!(flags & SuppressFailMessageInLogWindow)) - outputWindow->appendError(sp_resp.exitMessage(binary, timeOutMS)); + outputWindow->appendError(response.exitMessage(binary, timeOutMS)); } - return sp_resp; + return response; } } // namespace VCSBase diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h index d9a22367981b7bbcd3ddc16ba7a40c323e0e4202..466e4991727e504818c9066fefebfe3722cee764 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.h +++ b/src/plugins/vcsbase/vcsbaseplugin.h @@ -192,7 +192,9 @@ public: SuppressFailMessageInLogWindow = 0x10, // No message VCS about failure in VCS output window. SuppressCommandLogging = 0x20, // No command log entry in VCS output window. ShowSuccessMessage = 0x40, // Show message about successful completion in VCS output window. - ForceCLocale = 0x80 // Force C-locale for commands whose output is parsed. + ForceCLocale = 0x80, // Force C-locale for commands whose output is parsed. + FullySynchronously = 0x100 // Suppress local event loop (in case UI actions are + // triggered by file watchers). }; static Utils::SynchronousProcessResponse