Commit 5364f5c1 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

VCS: Show message box on timeouts/Add SSH prompt.

- Use message boxes on timeouts.
- Add a configuration for a graphical SSH password prompt binary with
defaults
- Launch commands that require authentification with no terminal on UNIX
and environment variable SSH_ASKPASS set accordingly.
- First attempt at introduce a common function to synchronously run VCS
commands in base plugin with flags.
- Use standard execution log entries in all VCS plugins (outputwindow).
parent 91c4b030
......@@ -473,7 +473,8 @@ void CVSPlugin::cvsDiff(const QString &workingDir, const QStringList &files)
// CVS returns the diff exit code (1 if files differ), which is
// undistinguishable from a "file not found" error, unfortunately.
const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, codec);
const CVSResponse response =
runCVS(workingDir, args, m_settings.timeOutMS(), 0, codec);
switch (response.result) {
case CVSResponse::NonNullExitCode:
case CVSResponse::Ok:
......@@ -560,7 +561,9 @@ void CVSPlugin::revertAll()
return;
QStringList args;
args << QLatin1String("update") << QLatin1String("-C") << state.topLevel();
const CVSResponse revertResponse = runCVS(state.topLevel(), args, m_settings.timeOutMS(), true);
const CVSResponse revertResponse =
runCVS(state.topLevel(), args, m_settings.timeOutMS(),
SshPasswordPrompt|ShowStdOutInLogWindow);
if (revertResponse.result == CVSResponse::Ok) {
cvsVersionControl()->emitRepositoryChanged(state.topLevel());
} else {
......@@ -574,7 +577,8 @@ void CVSPlugin::revertCurrentFile()
QTC_ASSERT(state.hasFile(), return)
QStringList args;
args << QLatin1String("diff") << state.relativeCurrentFile();
const CVSResponse diffResponse = runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(), false);
const CVSResponse diffResponse =
runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(), 0);
switch (diffResponse.result) {
case CVSResponse::Ok:
return; // Not modified, diff exit code 0
......@@ -595,7 +599,9 @@ void CVSPlugin::revertCurrentFile()
// revert
args.clear();
args << QLatin1String("update") << QLatin1String("-C") << state.relativeCurrentFile();
const CVSResponse revertResponse = runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(), true);
const CVSResponse revertResponse =
runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(),
SshPasswordPrompt|ShowStdOutInLogWindow);
if (revertResponse.result == CVSResponse::Ok) {
cvsVersionControl()->emitFilesChanged(QStringList(state.currentFile()));
}
......@@ -644,7 +650,8 @@ void CVSPlugin::startCommit(const QString &workingDir, const QStringList &files)
// We need the "Examining <subdir>" stderr output to tell
// where we are, so, have stdout/stderr channels merged.
QStringList args = QStringList(QLatin1String("status"));
const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, 0, true);
const CVSResponse response =
runCVS(workingDir, args, m_settings.timeOutMS(), MergeOutputChannels);
if (response.result != CVSResponse::Ok)
return;
// Get list of added/modified/deleted files and purge out undesired ones
......@@ -693,7 +700,9 @@ bool CVSPlugin::commit(const QString &messageFile,
QStringList args = QStringList(QLatin1String("commit"));
args << QLatin1String("-F") << messageFile;
args.append(fileList);
const CVSResponse response = runCVS(m_commitRepository, args, m_settings.longTimeOutMS(), true);
const CVSResponse response =
runCVS(m_commitRepository, args, m_settings.longTimeOutMS(),
SshPasswordPrompt|ShowStdOutInLogWindow);
return response.result == CVSResponse::Ok ;
}
......@@ -729,7 +738,9 @@ void CVSPlugin::filelog(const QString &workingDir,
QStringList args;
args << QLatin1String("log");
args.append(files);
const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, codec);
const CVSResponse response =
runCVS(workingDir, args, m_settings.timeOutMS(),
SshPasswordPrompt, codec);
if (response.result != CVSResponse::Ok)
return;
......@@ -755,7 +766,9 @@ void CVSPlugin::updateProject()
QStringList args(QLatin1String("update"));
args.push_back(QLatin1String("-dR"));
args.append(state.relativeCurrentProject());
const CVSResponse response = runCVS(state.currentProjectTopLevel(), args, m_settings.longTimeOutMS(), true);
const CVSResponse response =
runCVS(state.currentProjectTopLevel(), args, m_settings.longTimeOutMS(),
SshPasswordPrompt|ShowStdOutInLogWindow);
if (response.result == CVSResponse::Ok)
cvsVersionControl()->emitRepositoryChanged(state.currentProjectTopLevel());
}
......@@ -786,7 +799,9 @@ void CVSPlugin::annotate(const QString &workingDir, const QString &file,
if (!revision.isEmpty())
args << QLatin1String("-r") << revision;
args << file;
const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, codec);
const CVSResponse response =
runCVS(workingDir, args, m_settings.timeOutMS(),
SshPasswordPrompt, codec);
if (response.result != CVSResponse::Ok)
return;
......@@ -813,7 +828,8 @@ void CVSPlugin::projectStatus()
QTC_ASSERT(state.hasProject(), return)
QStringList args;
args << QLatin1String("status") << state.relativeCurrentProject();
const CVSResponse response = runCVS(state.currentProjectTopLevel(), args, m_settings.timeOutMS(), false);
const CVSResponse response =
runCVS(state.currentProjectTopLevel(), args, m_settings.timeOutMS(), 0);
if (response.result == CVSResponse::Ok)
showOutputInEditor(tr("Project status"), response.stdOut, VCSBase::RegularCommandOutput, state.currentProjectTopLevel(), 0);
}
......@@ -857,7 +873,8 @@ bool CVSPlugin::describe(const QString &toplevel, const QString &file, const
// Run log to obtain commit id and details
QStringList args;
args << QLatin1String("log") << (QLatin1String("-r") + changeNr) << file;
const CVSResponse logResponse = runCVS(toplevel, args, m_settings.timeOutMS(), false);
const CVSResponse logResponse =
runCVS(toplevel, args, m_settings.timeOutMS(), SshPasswordPrompt);
if (logResponse.result != CVSResponse::Ok) {
*errorMessage = logResponse.message;
return false;
......@@ -878,7 +895,8 @@ bool CVSPlugin::describe(const QString &toplevel, const QString &file, const
args.clear();
args << QLatin1String("log") << QLatin1String("-d") << (dateS + QLatin1Char('<') + nextDayS);
const CVSResponse repoLogResponse = runCVS(toplevel, args, m_settings.longTimeOutMS(), false);
const CVSResponse repoLogResponse =
runCVS(toplevel, args, m_settings.longTimeOutMS(), SshPasswordPrompt);
if (repoLogResponse.result != CVSResponse::Ok) {
*errorMessage = repoLogResponse.message;
return false;
......@@ -914,7 +932,8 @@ bool CVSPlugin::describe(const QString &repositoryPath,
// Run log
QStringList args(QLatin1String("log"));
args << (QLatin1String("-r") + it->revisions.front().revision) << it->file;
const CVSResponse logResponse = runCVS(repositoryPath, args, m_settings.timeOutMS(), false);
const CVSResponse logResponse =
runCVS(repositoryPath, args, m_settings.timeOutMS(), SshPasswordPrompt);
if (logResponse.result != CVSResponse::Ok) {
*errorMessage = logResponse.message;
return false;
......@@ -930,7 +949,8 @@ bool CVSPlugin::describe(const QString &repositoryPath,
args << m_settings.cvsDiffOptions << QLatin1String("-r") << previousRev
<< QLatin1String("-r") << it->revisions.front().revision
<< it->file;
const CVSResponse diffResponse = runCVS(repositoryPath, args, m_settings.timeOutMS(), false, codec);
const CVSResponse diffResponse =
runCVS(repositoryPath, args, m_settings.timeOutMS(), 0, codec);
switch (diffResponse.result) {
case CVSResponse::Ok:
case CVSResponse::NonNullExitCode: // Diff exit code != 0
......@@ -970,29 +990,13 @@ void CVSPlugin::submitCurrentLog()
<< Core::EditorManager::instance()->currentEditor());
}
static inline QString processStdErr(QProcess &proc)
{
return QString::fromLocal8Bit(proc.readAllStandardError()).remove(QLatin1Char('\r'));
}
// Format log entry for command
static inline QString msgExecutionLogEntry(const QString &workingDir, const QString &executable, const QStringList &arguments)
{
//: Executing: <executable> <arguments>
const QString args = arguments.join(QString(QLatin1Char(' ')));
if (workingDir.isEmpty())
return CVSPlugin::tr("Executing: %1 %2\n").arg(executable, args);
return CVSPlugin::tr("Executing in %1: %2 %3\n").
arg(QDir::toNativeSeparators(workingDir), executable, args);
}
// Run CVS. At this point, file arguments must be relative to
// the working directory (see above).
CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
const QStringList &arguments,
int timeOut,
bool showStdOutInOutputWindow, QTextCodec *outputCodec,
bool mergeStderr)
unsigned flags,
QTextCodec *outputCodec)
{
const QString executable = m_settings.cvsCommand;
CVSResponse response;
......@@ -1001,37 +1005,12 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
response.message =tr("No cvs executable specified!");
return response;
}
// Fix files and compile complete arguments
const QStringList allArgs = m_settings.addOptions(arguments);
const QString outputText = msgExecutionLogEntry(workingDirectory, executable, allArgs);
VCSBase::VCSBaseOutputWindow::instance()->appendCommand(outputText);
if (CVS::Constants::debug)
qDebug() << "runCVS" << timeOut << outputText;
// Run, connect stderr to the output window
Utils::SynchronousProcess process;
if (!workingDirectory.isEmpty())
process.setWorkingDirectory(workingDirectory);
if (mergeStderr)
process.setProcessChannelMode(QProcess::MergedChannels);
process.setTimeout(timeOut);
process.setStdOutCodec(outputCodec);
const Utils::SynchronousProcessResponse sp_resp =
runVCS(workingDirectory, executable,
m_settings.addOptions(arguments),
timeOut, flags, outputCodec);
process.setStdErrBufferedSignalsEnabled(true);
VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
// connect stdout to the output window if desired
if (showStdOutInOutputWindow) {
process.setStdOutBufferedSignalsEnabled(true);
connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
}
const Utils::SynchronousProcessResponse sp_resp = process.run(executable, allArgs);
response.result = CVSResponse::OtherError;
response.stdErr = sp_resp.stdErr;
response.stdOut = sp_resp.stdOut;
......@@ -1041,20 +1020,15 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
break;
case Utils::SynchronousProcessResponse::FinishedError:
response.result = CVSResponse::NonNullExitCode;
response.message = tr("The process terminated with exit code %1.").arg(sp_resp.exitCode);
break;
case Utils::SynchronousProcessResponse::TerminatedAbnormally:
response.message = tr("The process terminated abnormally.");
break;
case Utils::SynchronousProcessResponse::StartFailed:
response.message = tr("Could not start cvs '%1'. Please check your settings in the preferences.").arg(executable);
break;
case Utils::SynchronousProcessResponse::Hang:
response.message = tr("CVS did not respond within timeout limit (%1 ms).").arg(timeOut);
break;
}
if (response.result != CVSResponse::Ok)
VCSBase::VCSBaseOutputWindow::instance()->appendError(response.message);
response.message = sp_resp.exitMessage(executable, timeOut);
return response;
}
......@@ -1110,7 +1084,9 @@ bool CVSPlugin::vcsAdd(const QString &workingDir, const QString &rawFileName)
{
QStringList args;
args << QLatin1String("add") << rawFileName;
const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), true);
const CVSResponse response =
runCVS(workingDir, args, m_settings.timeOutMS(),
SshPasswordPrompt|ShowStdOutInLogWindow);
return response.result == CVSResponse::Ok;
}
......@@ -1118,7 +1094,9 @@ bool CVSPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName)
{
QStringList args;
args << QLatin1String("remove") << QLatin1String("-f") << rawFileName;
const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), true);
const CVSResponse response =
runCVS(workingDir, args, m_settings.timeOutMS(),
SshPasswordPrompt|ShowStdOutInLogWindow);
return response.result == CVSResponse::Ok;
}
......
......@@ -133,8 +133,7 @@ private:
CVSResponse runCVS(const QString &workingDirectory,
const QStringList &arguments,
int timeOut,
bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0,
bool mergeStderr = false);
unsigned flags, QTextCodec *outputCodec = 0);
void annotate(const QString &workingDir, const QString &file,
const QString &revision = QString(), int lineNumber= -1);
......
......@@ -232,7 +232,7 @@ static QList<ProcData> unixProcessListPS()
if (!psProcess.waitForStarted())
return rc;
QByteArray output;
if (!Utils::SynchronousProcess::readDataFromProcess(psProcess, 30000, &output))
if (!Utils::SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, 0, false))
return rc;
// Split "457 S+ /Users/foo.app"
const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
......
......@@ -112,8 +112,9 @@ QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizardPage::createCheckoutJob(
args << QLatin1String("clone") << repository() << checkoutDir;
const QString binary = args.front();
args.pop_front();
VCSBase::AbstractCheckoutJob *job = new VCSBase::ProcessCheckoutJob(binary, args, workingDirectory,
client->processEnvironment());
VCSBase::AbstractCheckoutJob *job =
new VCSBase::ProcessCheckoutJob(binary, args, workingDirectory,
client->processEnvironment().toStringList());
return QSharedPointer<VCSBase::AbstractCheckoutJob>(job);
}
......
......@@ -123,13 +123,6 @@ static inline QString msgParseFilesFailed()
return GitClient::tr("Unable to parse the file output.");
}
// Format a command for the status window
static QString formatCommand(const QString &binary, const QStringList &args)
{
//: Executing: <executable> <arguments>
return GitClient::tr("Executing: %1 %2\n").arg(binary, args.join(QString(QLatin1Char(' '))));
}
// ---------------- GitClient
const char *GitClient::stashNamePrefix = "stash@{";
......@@ -226,20 +219,20 @@ void GitClient::diff(const QString &workingDirectory,
if (unstagedFileNames.empty() && stagedFileNames.empty()) {
QStringList arguments(commonDiffArgs);
arguments << diffArgs;
outputWindow()->appendCommand(formatCommand(binary, arguments));
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, m_settings.timeoutSeconds);
} else {
// Files diff.
if (!unstagedFileNames.empty()) {
QStringList arguments(commonDiffArgs);
arguments << QLatin1String("--") << unstagedFileNames;
outputWindow()->appendCommand(formatCommand(binary, arguments));
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, m_settings.timeoutSeconds);
}
if (!stagedFileNames.empty()) {
QStringList arguments(commonDiffArgs);
arguments << QLatin1String("--cached") << diffArgs << QLatin1String("--") << stagedFileNames;
outputWindow()->appendCommand(formatCommand(binary, arguments));
outputWindow()->appendCommand(workingDirectory, binary, arguments);
command->addJob(arguments, m_settings.timeoutSeconds);
}
}
......@@ -1061,12 +1054,14 @@ GitCommand *GitClient::executeGit(const QString &workingDirectory,
VCSBase::VCSBaseEditor* editor,
bool outputToWindow,
GitCommand::TerminationReportMode tm,
int editorLineNumber)
int editorLineNumber,
bool unixTerminalDisabled)
{
outputWindow()->appendCommand(formatCommand(QLatin1String(Constants::GIT_BINARY), arguments));
outputWindow()->appendCommand(workingDirectory, QLatin1String(Constants::GIT_BINARY), arguments);
GitCommand *command = createCommand(workingDirectory, editor, outputToWindow, editorLineNumber);
command->addJob(arguments, m_settings.timeoutSeconds);
command->setTerminationReportMode(tm);
command->setUnixTerminalDisabled(unixTerminalDisabled);
command->execute();
return command;
}
......@@ -1083,14 +1078,14 @@ QStringList GitClient::binary() const
#endif
}
QStringList GitClient::processEnvironment() const
QProcessEnvironment GitClient::processEnvironment() const
{
ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment();
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
if (m_settings.adoptPath)
environment.set(QLatin1String("PATH"), m_settings.path);
// git svn runs perl which barfs at non-C locales.
environment.set(QLatin1String("LANG"), QString(QLatin1Char('C')));
return environment.toStringList();
environment.insert(QLatin1String("PATH"), m_settings.path);
// Set up SSH and C locale (required by git using perl).
VCSBase::VCSBasePlugin::setProcessEnvironment(&environment);
return environment;
}
bool GitClient::synchronousGit(const QString &workingDirectory,
......@@ -1103,11 +1098,11 @@ bool GitClient::synchronousGit(const QString &workingDirectory,
qDebug() << "synchronousGit" << workingDirectory << gitArguments;
if (logCommandToWindow)
outputWindow()->appendCommand(formatCommand(m_binaryPath, gitArguments));
outputWindow()->appendCommand(workingDirectory, m_binaryPath, gitArguments);
QProcess process;
process.setWorkingDirectory(workingDirectory);
process.setEnvironment(processEnvironment());
process.setProcessEnvironment(processEnvironment());
QStringList args = binary(); // "cmd /c git" on Windows
const QString executable = args.front();
......@@ -1125,7 +1120,7 @@ bool GitClient::synchronousGit(const QString &workingDirectory,
}
if (!Utils::SynchronousProcess::readDataFromProcess(process, m_settings.timeoutSeconds * 1000,
outputText, errorText)) {
outputText, errorText, true)) {
*errorText->append(GitCommand::msgTimeout(m_settings.timeoutSeconds).toLocal8Bit());
Utils::SynchronousProcess::stopProcess(process);
return false;
......@@ -1506,7 +1501,10 @@ void GitClient::pull(const QString &workingDirectory, bool rebase)
QStringList arguments(QLatin1String("pull"));
if (rebase)
arguments << QLatin1String("--rebase");
GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true, GitCommand::ReportStderr);
// Disable UNIX terminals to suppress SSH prompting.
GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true,
GitCommand::ReportStderr, -1,
VCSBase::VCSBasePlugin::isSshPromptConfigured());
connectRepositoryChanged(workingDirectory, cmd);
// Need to clean up if something goes wrong
if (rebase) {
......@@ -1539,7 +1537,11 @@ void GitClient::subversionFetch(const QString &workingDirectory)
{
QStringList args;
args << QLatin1String("svn") << QLatin1String("fetch");
GitCommand *cmd = executeGit(workingDirectory, args, 0, true, GitCommand::ReportStderr);
// Disable UNIX terminals to suppress SSH prompting.
GitCommand *cmd = executeGit(workingDirectory, args, 0, true, GitCommand::ReportStderr,
-1, true);
// Enable SSH prompting
cmd->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
connectRepositoryChanged(workingDirectory, cmd);
}
......@@ -1563,7 +1565,10 @@ void GitClient::subversionLog(const QString &workingDirectory)
void GitClient::push(const QString &workingDirectory)
{
executeGit(workingDirectory, QStringList(QLatin1String("push")), 0, true, GitCommand::ReportStderr);
// Disable UNIX terminals to suppress SSH prompting.
executeGit(workingDirectory, QStringList(QLatin1String("push")), 0,
true, GitCommand::ReportStderr,
VCSBase::VCSBasePlugin::isSshPromptConfigured());
}
QString GitClient::msgNoChangedFiles()
......
......@@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE
class QErrorMessage;
class QSignalMapper;
class QDebug;
class QProcessEnvironment;
QT_END_NAMESPACE
namespace Core {
......@@ -202,7 +203,7 @@ public:
void setSettings(const GitSettings &s);
QStringList binary() const; // Executable + basic arguments
QStringList processEnvironment() const;
QProcessEnvironment processEnvironment() const;
static QString msgNoChangedFiles();
......@@ -233,7 +234,8 @@ private:
VCSBase::VCSBaseEditor* editor = 0,
bool outputToWindow = false,
GitCommand::TerminationReportMode tm = GitCommand::NoReport,
int editorLineNumber = -1);
int editorLineNumber = -1,
bool unixTerminalDisabled = false);
bool synchronousGit(const QString &workingDirectory,
const QStringList &arguments,
......
......@@ -70,13 +70,14 @@ GitCommand::Job::Job(const QStringList &a, int t) :
GitCommand::GitCommand(const QStringList &binary,
const QString &workingDirectory,
const QStringList &environment,
const QProcessEnvironment&environment,
const QVariant &cookie) :
m_binaryPath(binary.front()),
m_basicArguments(binary),
m_workingDirectory(workingDirectory),
m_environment(environment),
m_cookie(cookie),
m_unixTerminalDisabled(false),
m_reportTerminationMode(NoReport)
{
m_basicArguments.pop_front();
......@@ -92,6 +93,16 @@ void GitCommand::setTerminationReportMode(TerminationReportMode m)
m_reportTerminationMode = m;
}
bool GitCommand::unixTerminalDisabled() const
{
return m_unixTerminalDisabled;
}
void GitCommand::setUnixTerminalDisabled(bool e)
{
m_unixTerminalDisabled = e;
}
void GitCommand::addJob(const QStringList &arguments, int timeout)
{
m_jobs.push_back(Job(arguments, timeout));
......@@ -121,12 +132,18 @@ QString GitCommand::msgTimeout(int seconds)
void GitCommand::run()
{
if (Git::Constants::debug)
qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size();
QProcess process;
qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size()
<< "terminal_disabled" << m_unixTerminalDisabled;
const unsigned processFlags = m_unixTerminalDisabled ?
unsigned(Utils::SynchronousProcess::UnixTerminalDisabled) :
unsigned(0);
const QSharedPointer<QProcess> process =
Utils::SynchronousProcess::createProcess(processFlags);
if (!m_workingDirectory.isEmpty())
process.setWorkingDirectory(m_workingDirectory);
process->setWorkingDirectory(m_workingDirectory);
process.setEnvironment(m_environment);
process->setProcessEnvironment(m_environment);
QByteArray stdOut;
QByteArray stdErr;
......@@ -139,25 +156,25 @@ void GitCommand::run()
if (Git::Constants::debug)
qDebug() << "GitCommand::run" << j << '/' << count << m_jobs.at(j).arguments;
process.start(m_binaryPath, m_basicArguments + m_jobs.at(j).arguments);
if(!process.waitForStarted()) {
process->start(m_binaryPath, m_basicArguments + m_jobs.at(j).arguments);
if(!process->waitForStarted()) {
ok = false;
error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process.errorString());
error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process->errorString());
break;
}
process.closeWriteChannel();
process->closeWriteChannel();
const int timeOutSeconds = m_jobs.at(j).timeout;
if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOutSeconds * 1000,
&stdOut, &stdErr)) {
Utils::SynchronousProcess::stopProcess(process);
if (!Utils::SynchronousProcess::readDataFromProcess(*process, timeOutSeconds * 1000,
&stdOut, &stdErr, false)) {
Utils::SynchronousProcess::stopProcess(*process);
ok = false;
error += msgTimeout(timeOutSeconds);
break;
}
error += QString::fromLocal8Bit(stdErr);
exitCode = process.exitCode();
exitCode = process->exitCode();
switch (m_reportTerminationMode) {
case NoReport:
break;
......
......@@ -33,6 +33,7 @@
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtCore/QProcessEnvironment>
QT_BEGIN_NAMESPACE
class QProcess;
......@@ -55,7 +56,7 @@ public:
explicit GitCommand(const QStringList &binary,
const QString &workingDirectory,
const QStringList &environment,
const QProcessEnvironment &environment,
const QVariant &cookie = QVariant());
......@@ -70,6 +71,10 @@ public:
TerminationReportMode reportTerminationMode() const;
void setTerminationReportMode(TerminationReportMode m);
// Disable Terminal on UNIX (see VCS SSH handling).
bool unixTerminalDisabled() const;
void setUnixTerminalDisabled(bool);
static QString msgTimeout(int seconds);
void setCookie(const QVariant &cookie);
......@@ -95,8 +100,9 @@ private:
const QString m_binaryPath;
QStringList m_basicArguments;
const QString m_workingDirectory;
const QStringList m_environment;
const QProcessEnvironment m_environment;
QVariant m_cookie;
bool m_unixTerminalDisabled;
QList<Job> m_jobs;
TerminationReportMode m_reportTerminationMode;
......
......@@ -136,7 +136,7 @@ bool MercurialClient::executeHgSynchronously(const QString &workingDir,
const QStringList arguments = settings.standardArguments() + args;
VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
outputWindow->appendCommand(MercurialJobRunner::msgExecute(binary, arguments));
outputWindow->appendCommand(workingDir, binary, args);
hgProcess.start(binary, arguments);
......@@ -149,7 +149,7 @@ bool MercurialClient::executeHgSynchronously(const QString &workingDir,
QByteArray stdErr;
if (!Utils::SynchronousProcess::readDataFromProcess(hgProcess, settings.timeoutMilliSeconds(),
output, &stdErr)) {
output, &stdErr, true)) {
Utils::SynchronousProcess::stopProcess(hgProcess);
outputWindow->appendError(MercurialJobRunner::msgTimeout(settings.timeoutSeconds()));
return false;
......@@ -457,6 +457,8 @@ void MercurialClient::pull(const QString &repositoryRoot, const QString &reposit