Commit ad9b4ce4 authored by Cristian Adam's avatar Cristian Adam Committed by Alexander Drozdov

Perforce: Ability to use multiple workspaces/projects

By the use of P4CONFIG (p4config.txt) one can now specify workspace
details (P4USER, P4CLIENT, P4PORT) individually for specific projects.

Previously one had to reconfigure Qt Creator in Settings for every
workspace switch.

Change-Id: I117829ab3cf592562a4662f85314aa3c125e7610
Task-number: QTCREATORBUG-14378
Reviewed-by: default avatarAlexander Drozdov <adrozdoff@gmail.com>
Reviewed-by: default avatarTobias Hunger <tobias.hunger@theqtcompany.com>
parent d2522905
......@@ -29,6 +29,7 @@
****************************************************************************/
#include "perforcechecker.h"
#include "perforceconstants.h"
#include <utils/qtcassert.h>
#include <utils/synchronousprocess.h>
......@@ -69,6 +70,11 @@ bool PerforceChecker::isRunning() const
return m_process.state() == QProcess::Running;
}
bool PerforceChecker::waitForFinished(int msec)
{
return m_process.waitForFinished(msec);
}
void PerforceChecker::resetOverrideCursor()
{
if (m_isOverrideCursor) {
......@@ -77,7 +83,7 @@ void PerforceChecker::resetOverrideCursor()
}
}
void PerforceChecker::start(const QString &binary,
void PerforceChecker::start(const QString &binary, const QString &workingDirectory,
const QStringList &basicArgs,
int timeoutMS)
{
......@@ -92,6 +98,10 @@ void PerforceChecker::start(const QString &binary,
m_binary = binary;
QStringList args = basicArgs;
args << QLatin1String("client") << QLatin1String("-o");
if (!workingDirectory.isEmpty())
m_process.setWorkingDirectory(workingDirectory);
m_process.start(m_binary, args);
m_process.closeWriteChannel();
// Timeout handling
......
......@@ -50,11 +50,14 @@ public:
public slots:
void start(const QString &binary,
const QString &workingDirectory,
const QStringList &basicArgs = QStringList(),
int timeoutMS = -1);
bool isRunning() const;
bool waitForFinished(int msec = -1);
bool useOverideCursor() const;
void setUseOverideCursor(bool v);
......
......@@ -865,29 +865,46 @@ bool PerforcePlugin::managesFile(const QString &workingDirectory, const QString
bool PerforcePlugin::managesDirectoryFstat(const QString &directory)
{
if (!m_settings.isValid())
return false;
// Cached?
const ManagedDirectoryCache::const_iterator cit = m_managedDirectoryCache.constFind(directory);
if (cit != m_managedDirectoryCache.constEnd())
return cit.value();
if (cit != m_managedDirectoryCache.constEnd()) {
const DirectoryCacheEntry &entry = cit.value();
setTopLevel(entry.m_topLevel);
return entry.m_isManaged;
}
if (!m_settings.isValid()) {
if (m_settings.topLevel().isEmpty() && m_settings.defaultEnv())
getTopLevel(directory, true);
if (!m_settings.isValid())
return false;
}
// Determine value and insert into cache
bool managed = false;
do {
// Quick check: Must be at or below top level and not "../../other_path"
const QString relativeDirArgs = m_settings.relativeToTopLevelArguments(directory);
if (!relativeDirArgs.isEmpty() && relativeDirArgs.startsWith(QLatin1String("..")))
break;
if (!relativeDirArgs.isEmpty() && relativeDirArgs.startsWith(QLatin1String(".."))) {
if (!m_settings.defaultEnv())
break;
else
getTopLevel(directory, true);
}
// Is it actually managed by perforce?
QStringList args;
args << QLatin1String("fstat") << QLatin1String("-m1") << perforceRelativeFileArguments(relativeDirArgs);
const PerforceResponse result = runP4Cmd(m_settings.topLevel(), args,
RunFullySynchronous);
if (Perforce::Constants::debug)
qDebug() << "Perforce result:\n" << result.stdOut << "\n---\n" << result.stdErr
<< "\n---\n" << result.message;
managed = result.stdOut.contains(QLatin1String("depotFile"))
|| result.stdErr.contains(QLatin1String("... - no such file(s)"));
} while (false);
m_managedDirectoryCache.insert(directory, managed);
m_managedDirectoryCache.insert(directory, DirectoryCacheEntry(managed, m_settings.topLevel()));
return managed;
}
......@@ -1529,14 +1546,17 @@ PerforceVersionControl *PerforcePlugin::perforceVersionControl()
return static_cast<PerforceVersionControl *>(m_instance->versionControl());
}
void PerforcePlugin::slotTopLevelFound(const QString &t)
void PerforcePlugin::setTopLevel(const QString &topLevel)
{
m_settings.setTopLevel(t);
const QString msg = tr("Perforce repository: %1").
arg(QDir::toNativeSeparators(t));
if (m_settings.topLevel() == topLevel)
return;
m_settings.setTopLevel(topLevel);
const QString msg = tr("Perforce repository: %1").arg(QDir::toNativeSeparators(topLevel));
VcsOutputWindow::appendSilently(msg);
if (Perforce::Constants::debug)
qDebug() << "P4: " << t;
qDebug() << "P4: " << topLevel;
}
void PerforcePlugin::slotTopLevelFailed(const QString &errorMessage)
......@@ -1546,7 +1566,7 @@ void PerforcePlugin::slotTopLevelFailed(const QString &errorMessage)
qDebug() << errorMessage;
}
void PerforcePlugin::getTopLevel()
void PerforcePlugin::getTopLevel(const QString &workingDirectory, bool isSync)
{
// Run a new checker
if (m_instance->m_settings.p4BinaryPath().isEmpty())
......@@ -1554,9 +1574,14 @@ void PerforcePlugin::getTopLevel()
auto checker = new PerforceChecker(m_instance);
connect(checker, &PerforceChecker::failed, m_instance, &PerforcePlugin::slotTopLevelFailed);
connect(checker, &PerforceChecker::failed, checker, &QObject::deleteLater);
connect(checker, &PerforceChecker::succeeded, m_instance, &PerforcePlugin::slotTopLevelFound);
connect(checker, &PerforceChecker::succeeded, m_instance, &PerforcePlugin::setTopLevel);
connect(checker, &PerforceChecker::succeeded,checker, &QObject::deleteLater);
checker->start(settings().p4BinaryPath(), settings().commonP4Arguments(QString()), 30000);
checker->start(settings().p4BinaryPath(), workingDirectory,
settings().commonP4Arguments(QString()), 30000);
if (isSync)
checker->waitForFinished();
}
#ifdef WITH_TESTS
......
......@@ -136,7 +136,7 @@ private slots:
void submitCurrentLog();
void printPendingChanges();
void slotSubmitDiff(const QStringList &files);
void slotTopLevelFound(const QString &);
void setTopLevel(const QString &);
void slotTopLevelFailed(const QString &);
#ifdef WITH_TESTS
......@@ -148,7 +148,19 @@ protected:
private:
typedef QHash<QString, bool> ManagedDirectoryCache;
class DirectoryCacheEntry
{
public:
DirectoryCacheEntry(bool isManaged, const QString &topLevel):
m_isManaged(isManaged), m_topLevel(topLevel)
{
}
bool m_isManaged;
QString m_topLevel;
};
typedef QHash<QString, DirectoryCacheEntry> ManagedDirectoryCache;
Core::IEditor *showOutputInEditor(const QString &title, const QString &output,
int editorType, const QString &source,
......@@ -197,7 +209,8 @@ private:
bool isCommitEditorOpen() const;
static QSharedPointer<Utils::TempFileSaver> createTemporaryArgumentFile(const QStringList &extraArgs,
QString *errorString);
static void getTopLevel();
static void getTopLevel(const QString &workingDirectory = QString(), bool isSync = false);
QString pendingChangesData();
void updateCheckout(const QString &workingDir = QString(),
......
......@@ -68,7 +68,7 @@ void SettingsPageWidget::slotTest()
setStatusText(tr("Testing..."));
const Settings s = settings();
m_checker->start(s.p4BinaryPath, s.commonP4Arguments(), 10000);
m_checker->start(s.p4BinaryPath, QString(), s.commonP4Arguments(), 10000);
}
void SettingsPageWidget::testSucceeded(const QString &repo)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment