From 469639fb3c532c54ef03852b08f162ffd227c994 Mon Sep 17 00:00:00 2001 From: dt Date: Thu, 19 Feb 2009 16:11:29 +0100 Subject: Fixes: Make QtCreator fly even in face of perforce misconfiguration. Details: If p4 is in path, but the server isn't configured correctly we were pretty slow, this fixes that by running p4 client -o after the settings have changed, if that doesn't return after 2 seconds, then we cache that as a invalid configuration. --- .../cmakeprojectmanager/cmakeprojectmanager.h | 4 +- src/plugins/perforce/perforceplugin.cpp | 65 +++++----- src/plugins/perforce/perforceplugin.h | 5 +- src/plugins/perforce/perforcesettings.cpp | 131 ++++++++++++++++++--- src/plugins/perforce/perforcesettings.h | 38 ++++-- src/plugins/perforce/settingspage.cpp | 42 ++++--- src/plugins/perforce/settingspage.h | 7 +- 7 files changed, 207 insertions(+), 85 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h index d8a61e6e80..3a8dda54aa 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h @@ -71,14 +71,14 @@ class CMakeRunner { public: CMakeRunner(); - void run(QFutureInterface &fi); void setExecutable(const QString &executable); QString executable() const; QString version() const; bool supportsQtCreator() const; - void waitForUpToDate() const; private: + void run(QFutureInterface &fi); + void waitForUpToDate() const; QString m_executable; QString m_version; bool m_supportsQtCreator; diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 7d126c4bb9..b4685419c0 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -221,7 +221,6 @@ bool PerforcePlugin::initialize(const QStringList &arguments, QString *errorMess m_coreListener = new CoreListener(this); addObject(m_coreListener); - //register actions Core::ActionManager *am = Core::ICore::instance()->actionManager(); @@ -682,6 +681,8 @@ void PerforcePlugin::updateActions() bool PerforcePlugin::managesDirectory(const QString &directory) const { + if (!checkP4Command()) + return false; const QString p4Path = directory + QLatin1String("/..."); QStringList args; args << QLatin1String("fstat") << QLatin1String("-m1") << p4Path; @@ -758,7 +759,7 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args, tempfile.setAutoRemove(true); const QChar newLine = QLatin1Char('\n'); const QChar blank = QLatin1Char(' '); - QStringList actualArgs = basicP4Args(); + QStringList actualArgs = m_settings.basicP4Args(); if (!extraArgs.isEmpty()) { if (tempfile.open()) { QTextStream stream(&tempfile); @@ -773,7 +774,7 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args, actualArgs << args; if (logFlags & CommandToWindow) { - QString command = m_settings.p4Command; + QString command = m_settings.p4Command(); command += blank; command += actualArgs.join(QString(blank)); const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm")); @@ -799,7 +800,7 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args, connect(&process, SIGNAL(stdOutBuffered(QString,bool)), m_perforceOutputWindow, SLOT(append(QString,bool))); } - const Core::Utils::SynchronousProcessResponse sp_resp = process.run(m_settings.p4Command, actualArgs); + const Core::Utils::SynchronousProcessResponse sp_resp = process.run(m_settings.p4Command(), actualArgs); if (Perforce::Constants::debug) qDebug() << sp_resp; @@ -817,7 +818,7 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args, response.message = tr("The process terminated abnormally."); break; case Core::Utils::SynchronousProcessResponse::StartFailed: - response.message = tr("Could not start perforce '%1'. Please check your settings in the preferences.").arg(m_settings.p4Command); + response.message = tr("Could not start perforce '%1'. Please check your settings in the preferences.").arg(m_settings.p4Command()); break; case Core::Utils::SynchronousProcessResponse::Hang: response.message = tr("Perforce did not respond within timeout limit (%1 ms).").arg(p4Timeout ); @@ -969,8 +970,8 @@ bool PerforcePlugin::editorAboutToClose(Core::IEditor *editor) proc.setEnvironment(environment()); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - proc.start(m_settings.p4Command, - basicP4Args() << QLatin1String("submit") << QLatin1String("-i")); + proc.start(m_settings.p4Command(), + m_settings.basicP4Args() << QLatin1String("submit") << QLatin1String("-i")); if (!proc.waitForStarted(p4Timeout)) { showOutput(tr("Cannot execute p4 submit."), true); QApplication::restoreOverrideCursor(); @@ -1018,8 +1019,8 @@ QString PerforcePlugin::clientFilePath(const QString &serverFilePath) QApplication::setOverrideCursor(Qt::WaitCursor); QProcess proc; proc.setEnvironment(environment()); - proc.start(m_settings.p4Command, - basicP4Args() << QLatin1String("fstat") << serverFilePath); + proc.start(m_settings.p4Command(), + m_settings.basicP4Args() << QLatin1String("fstat") << serverFilePath); QString path; if (proc.waitForFinished(3000)) { @@ -1047,22 +1048,9 @@ QString PerforcePlugin::currentFileName() return fileName; } -QStringList PerforcePlugin::basicP4Args() const -{ - QStringList lst; - if (!m_settings.defaultEnv) { - lst << QLatin1String("-c") << m_settings.p4Client; - lst << QLatin1String("-p") << m_settings.p4Port; - lst << QLatin1String("-u") << m_settings.p4User; - } - return lst; -} - bool PerforcePlugin::checkP4Command() const { - if (m_settings.p4Command.isEmpty()) - return false; - return true; + return m_settings.isValid(); } QString PerforcePlugin::pendingChangesData() @@ -1074,8 +1062,8 @@ QString PerforcePlugin::pendingChangesData() QString user; QProcess proc; proc.setEnvironment(environment()); - proc.start(m_settings.p4Command, - basicP4Args() << QLatin1String("info")); + proc.start(m_settings.p4Command(), + m_settings.basicP4Args() << QLatin1String("info")); if (proc.waitForFinished(3000)) { QString output = QString::fromUtf8(proc.readAllStandardOutput()); if (!output.isEmpty()) { @@ -1087,8 +1075,8 @@ QString PerforcePlugin::pendingChangesData() } if (user.isEmpty()) return data; - proc.start(m_settings.p4Command, - basicP4Args() << QLatin1String("changes") << QLatin1String("-s") << QLatin1String("pending") << QLatin1String("-u") << user); + proc.start(m_settings.p4Command(), + m_settings.basicP4Args() << QLatin1String("changes") << QLatin1String("-s") << QLatin1String("pending") << QLatin1String("-u") << user); if (proc.waitForFinished(3000)) data = QString::fromUtf8(proc.readAllStandardOutput()); return data; @@ -1139,17 +1127,24 @@ PerforcePlugin::~PerforcePlugin() } } -PerforceSettings PerforcePlugin::settings() const +const PerforceSettings& PerforcePlugin::settings() const { return m_settings; } -void PerforcePlugin::setSettings(const PerforceSettings &s) +void PerforcePlugin::setSettings(const QString &p4Command, const QString &p4Port, const QString &p4Client, const QString p4User, bool defaultEnv) { - if (s != m_settings) { - m_settings = s; - if (QSettings *settings = Core::ICore::instance()->settings()) - m_settings.toSettings(settings); + + if (m_settings.p4Command() == p4Command + && m_settings.p4Port() == p4Port + && m_settings.p4Client() == p4Client + && m_settings.p4User() == p4User + && m_settings.defaultEnv() == defaultEnv) + { + // Nothing to do + } else { + m_settings.setSettings(p4Command, p4Port, p4Client, p4User, defaultEnv); + m_settings.toSettings(Core::ICore::instance()->settings()); } } @@ -1162,9 +1157,9 @@ QString PerforcePlugin::fileNameFromPerforceName(const QString& perforceName, return perforceName; // "where" remaps the file to client file tree QProcess proc; - QStringList args(basicP4Args()); + QStringList args(m_settings.basicP4Args()); args << QLatin1String("where") << perforceName; - proc.start(m_settings.p4Command, args); + proc.start(m_settings.p4Command(), args); if (!proc.waitForFinished()) { *errorMessage = tr("Timeout waiting for \"where\" (%1).").arg(perforceName); return QString(); diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h index e5985a28ab..d856685bba 100644 --- a/src/plugins/perforce/perforceplugin.h +++ b/src/plugins/perforce/perforceplugin.h @@ -93,7 +93,6 @@ public: PerforcePlugin(); ~PerforcePlugin(); - QStringList basicP4Args() const; SettingsPage *settingsPage() const { return m_settingsPage; } bool initialize(const QStringList &arguments, QString *error_message); @@ -113,8 +112,8 @@ public: static PerforcePlugin *perforcePluginInstance(); - PerforceSettings settings() const; - void setSettings(const PerforceSettings &s); + const PerforceSettings& settings() const; + void setSettings(const QString &p4Command, const QString &p4Port, const QString &p4Client, const QString p4User, bool defaultEnv); // Map a perforce name "//xx" to its real name in the file system QString fileNameFromPerforceName(const QString& perforceName, QString *errorMessage) const; diff --git a/src/plugins/perforce/perforcesettings.cpp b/src/plugins/perforce/perforcesettings.cpp index 7ba51b78e0..b30d12a414 100644 --- a/src/plugins/perforce/perforcesettings.cpp +++ b/src/plugins/perforce/perforcesettings.cpp @@ -33,7 +33,11 @@ #include "perforcesettings.h" +#include +#include #include +#include +#include static const char *groupC = "Perforce"; static const char *commandKeyC = "Command"; @@ -55,41 +59,134 @@ static QString defaultCommand() namespace Perforce { namespace Internal { -PerforceSettings::PerforceSettings() : - p4Command(defaultCommand()), - defaultEnv(true) +PerforceSettings::PerforceSettings() + : m_valid(false) { + // We do all the initialization in fromSettings +} + +PerforceSettings::~PerforceSettings() +{ + // ensure that we are not still running + m_future.waitForFinished(); +} + +bool PerforceSettings::isValid() const +{ + m_future.waitForFinished(); + m_mutex.lock(); + bool valid = m_valid; + m_mutex.unlock(); + return valid; +} + +void PerforceSettings::run(QFutureInterface &fi) +{ + m_mutex.lock(); + QString executable = m_p4Command; + QStringList arguments = basicP4Args(); + m_mutex.unlock(); + + // TODO actually check + bool valid = true; + + QProcess p4; + p4.start(m_p4Command, QStringList() << "client"<<"-o"); + p4.waitForFinished(2000); + if (p4.state() != QProcess::NotRunning) { + p4.kill(); + p4.waitForFinished(); + valid = false; + } else { + QString response = p4.readAllStandardOutput(); + if (!response.contains("View:")) + valid = false; + } + + m_mutex.lock(); + if (executable == m_p4Command && arguments == basicP4Args()) // Check that those settings weren't changed in between + m_valid = valid; + m_mutex.unlock(); + fi.reportFinished(); } void PerforceSettings::fromSettings(QSettings *settings) { + m_mutex.lock(); settings->beginGroup(QLatin1String(groupC)); - p4Command = settings->value(QLatin1String(commandKeyC), defaultCommand()).toString(); - defaultEnv = settings->value(QLatin1String(defaultKeyC), true).toBool(); - p4Port = settings->value(QLatin1String(portKeyC), QString()).toString(); - p4Client = settings->value(QLatin1String(clientKeyC), QString()).toString(); - p4User = settings->value(QLatin1String(userKeyC), QString()).toString(); + m_p4Command = settings->value(QLatin1String(commandKeyC), defaultCommand()).toString(); + m_defaultEnv = settings->value(QLatin1String(defaultKeyC), true).toBool(); + m_p4Port = settings->value(QLatin1String(portKeyC), QString()).toString(); + m_p4Client = settings->value(QLatin1String(clientKeyC), QString()).toString(); + m_p4User = settings->value(QLatin1String(userKeyC), QString()).toString(); settings->endGroup(); + m_mutex.unlock(); + m_future = QtConcurrent::run(&PerforceSettings::run, this); } void PerforceSettings::toSettings(QSettings *settings) const { + m_mutex.lock(); settings->beginGroup(QLatin1String(groupC)); - settings->setValue(commandKeyC, p4Command); - settings->setValue(defaultKeyC, defaultEnv); - settings->setValue(portKeyC, p4Port); - settings->setValue(clientKeyC, p4Client); - settings->setValue(userKeyC, p4User); + settings->setValue(commandKeyC, m_p4Command); + settings->setValue(defaultKeyC, m_defaultEnv); + settings->setValue(portKeyC, m_p4Port); + settings->setValue(clientKeyC, m_p4Client); + settings->setValue(userKeyC, m_p4User); settings->endGroup(); + m_mutex.unlock(); } -bool PerforceSettings::equals(const PerforceSettings &s) const +void PerforceSettings::setSettings(const QString &p4Command, const QString &p4Port, const QString &p4Client, const QString p4User, bool defaultEnv) { - return p4Command == s.p4Command && p4Port == s.p4Port - && p4Client == s.p4Client && p4User == s.p4User - && defaultEnv == s.defaultEnv; + m_mutex.lock(); + m_p4Command = p4Command; + m_p4Port = p4Port; + m_p4Client = p4Client; + m_p4User = p4User; + m_defaultEnv = defaultEnv; + m_valid = false; + m_mutex.unlock(); + m_future = QtConcurrent::run(&PerforceSettings::run, this); } +QString PerforceSettings::p4Command() const +{ + return m_p4Command; +} + +QString PerforceSettings::p4Port() const +{ + return m_p4Port; +} + +QString PerforceSettings::p4Client() const +{ + return m_p4Client; +} + +QString PerforceSettings::p4User() const +{ + return m_p4User; +} + +bool PerforceSettings::defaultEnv() const +{ + return m_defaultEnv; +} + +QStringList PerforceSettings::basicP4Args() const +{ + QStringList lst; + if (!m_defaultEnv) { + lst << QLatin1String("-c") << m_p4Client; + lst << QLatin1String("-p") << m_p4Port; + lst << QLatin1String("-u") << m_p4User; + } + return lst; +} + + } // Internal } // Perforce diff --git a/src/plugins/perforce/perforcesettings.h b/src/plugins/perforce/perforcesettings.h index 4451d4ad61..0ca1147f4f 100644 --- a/src/plugins/perforce/perforcesettings.h +++ b/src/plugins/perforce/perforcesettings.h @@ -35,6 +35,7 @@ #define PERFOCESETTINGS_H #include +#include QT_BEGIN_NAMESPACE class QSettings; @@ -43,23 +44,34 @@ QT_END_NAMESPACE namespace Perforce { namespace Internal { -struct PerforceSettings { +class PerforceSettings { +public: PerforceSettings(); - void fromSettings(QSettings *); + ~PerforceSettings(); + void fromSettings(QSettings *settings); void toSettings(QSettings *) const; - bool equals(const PerforceSettings &s) const; + void setSettings(const QString &p4Command, const QString &p4Port, const QString &p4Client, const QString p4User, bool defaultEnv); + bool isValid() const; - QString p4Command; - QString p4Port; - QString p4Client; - QString p4User; - bool defaultEnv; -}; + QString p4Command() const; + QString p4Port() const; + QString p4Client() const; + QString p4User() const; + bool defaultEnv() const; + QStringList basicP4Args() const; +private: + void run(QFutureInterface &fi); + mutable QFuture m_future; + mutable QMutex m_mutex; -inline bool operator==(const PerforceSettings &p1, const PerforceSettings &p2) - { return p1.equals(p2); } -inline bool operator!=(const PerforceSettings &p1, const PerforceSettings &p2) - { return !p1.equals(p2); } + QString m_p4Command; + QString m_p4Port; + QString m_p4Client; + QString m_p4User; + bool m_defaultEnv; + bool m_valid; + Q_DISABLE_COPY(PerforceSettings); +}; } // Internal } // Perforce diff --git a/src/plugins/perforce/settingspage.cpp b/src/plugins/perforce/settingspage.cpp index 70ef649b0e..53d32714ff 100644 --- a/src/plugins/perforce/settingspage.cpp +++ b/src/plugins/perforce/settingspage.cpp @@ -49,24 +49,38 @@ SettingsPageWidget::SettingsPageWidget(QWidget *parent) : m_ui.pathChooser->setExpectedKind(PathChooser::Command); } -PerforceSettings SettingsPageWidget::settings() const +QString SettingsPageWidget::p4Command() const { - PerforceSettings rc; - rc.p4Command = m_ui.pathChooser->path(); - rc.defaultEnv = m_ui.defaultCheckBox->isChecked(); - rc.p4Port = m_ui.portLineEdit->text(); - rc.p4Client = m_ui.clientLineEdit->text(); - rc.p4User = m_ui.userLineEdit->text(); - return rc; + return m_ui.pathChooser->path(); +} + +bool SettingsPageWidget::defaultEnv() const +{ + return m_ui.defaultCheckBox->isChecked(); +} + +QString SettingsPageWidget::p4Port() const +{ + return m_ui.portLineEdit->text(); +} + +QString SettingsPageWidget::p4User() const +{ + return m_ui.userLineEdit->text(); +} + +QString SettingsPageWidget::p4Client() const +{ + return m_ui.clientLineEdit->text(); } void SettingsPageWidget::setSettings(const PerforceSettings &s) { - m_ui.pathChooser->setPath(s.p4Command); - m_ui.defaultCheckBox->setChecked(s.defaultEnv); - m_ui.portLineEdit->setText(s.p4Port); - m_ui.clientLineEdit->setText(s.p4Client); - m_ui.userLineEdit->setText(s.p4User); + m_ui.pathChooser->setPath(s.p4Command()); + m_ui.defaultCheckBox->setChecked(s.defaultEnv()); + m_ui.portLineEdit->setText(s.p4Port()); + m_ui.clientLineEdit->setText(s.p4Client()); + m_ui.userLineEdit->setText(s.p4User()); } SettingsPage::SettingsPage() @@ -101,5 +115,5 @@ void SettingsPage::apply() if (!m_widget) return; - PerforcePlugin::perforcePluginInstance()->setSettings(m_widget->settings()); + PerforcePlugin::perforcePluginInstance()->setSettings(m_widget->p4Command(), m_widget->p4Port(), m_widget->p4Client(), m_widget->p4User(), m_widget->defaultEnv()); } diff --git a/src/plugins/perforce/settingspage.h b/src/plugins/perforce/settingspage.h index f5c43599fa..10a3a0c93b 100644 --- a/src/plugins/perforce/settingspage.h +++ b/src/plugins/perforce/settingspage.h @@ -51,7 +51,12 @@ class SettingsPageWidget : public QWidget { public: explicit SettingsPageWidget(QWidget *parent); - PerforceSettings settings() const; + QString p4Command() const; + bool defaultEnv() const; + QString p4Port() const; + QString p4User() const; + QString p4Client() const; + void setSettings(const PerforceSettings &); private: -- cgit v1.2.1