forked from qt-creator/qt-creator
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).
This commit is contained in:
@@ -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;
|
||||
if (!m_workingDirectory.isEmpty())
|
||||
process.setWorkingDirectory(m_workingDirectory);
|
||||
qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size()
|
||||
<< "terminal_disabled" << m_unixTerminalDisabled;
|
||||
|
||||
process.setEnvironment(m_environment);
|
||||
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->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;
|
||||
|
||||
Reference in New Issue
Block a user