VCS: Allow to run commands synchronously

Run some commands synchronously. This avoids issues with the UI
reacting to file changes done by the VCS on windows which can lead
to crashes.

Task-number: QTCREATORBUG-3021
Reviewed-by: Tobias Hunger
This commit is contained in:
Friedemann Kleint
2010-11-22 14:53:20 +01:00
committed by Tobias Hunger
parent a13014eb4e
commit 818f5f0e78
4 changed files with 116 additions and 39 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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,16 +814,25 @@ Utils::SynchronousProcessResponse
nsp << "suppress_log";
if (flags & ForceCLocale)
nsp << "c_locale";
if (flags & FullySynchronously)
nsp << "fully_synchronously";
if (outputCodec)
nsp << " Codec: " << outputCodec->name();
}
VCSBase::VCSBasePlugin::setProcessEnvironment(&env, (flags & ForceCLocale));
Utils::SynchronousProcessResponse response;
if (flags & FullySynchronously) {
response = runVCS_FullySynchronously(workingDir, binary, arguments, timeOutMS,
env, flags, outputCodec);
} else {
// 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)
@@ -785,18 +861,19 @@ Utils::SynchronousProcessResponse
process.setTimeOutMessageBoxEnabled(true);
// Run!
const Utils::SynchronousProcessResponse sp_resp = process.run(binary, arguments);
// Success/Fail message in appropriate window?
if (sp_resp.result == Utils::SynchronousProcessResponse::Finished) {
if (flags & ShowSuccessMessage)
outputWindow->append(sp_resp.exitMessage(binary, timeOutMS));
} else {
if (!(flags & SuppressFailMessageInLogWindow))
outputWindow->appendError(sp_resp.exitMessage(binary, timeOutMS));
response = process.run(binary, arguments);
}
return sp_resp;
// Success/Fail message in appropriate window?
if (response.result == Utils::SynchronousProcessResponse::Finished) {
if (flags & ShowSuccessMessage)
outputWindow->append(response.exitMessage(binary, timeOutMS));
} else {
if (!(flags & SuppressFailMessageInLogWindow))
outputWindow->appendError(response.exitMessage(binary, timeOutMS));
}
return response;
}
} // namespace VCSBase

View File

@@ -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