forked from qt-creator/qt-creator
IVersionControl: Implement topic cache in the base class
Derivatives need to derive TopicCache, implement its pure virtual functions and pass it in IVersionControl's constructor. Change-Id: I3a904c84541fda95eee75296f86441c4bae55d79 Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
c68ebeed2e
commit
cd48c5e513
@@ -28,7 +28,29 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "iversioncontrol.h"
|
||||
#include "vcsmanager.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
/*!
|
||||
* \class Core::IVersionControl::TopicCache
|
||||
* \brief The TopicCache class stores a {directory -> topic} cache
|
||||
*
|
||||
* In order to support topic, an IVersionControl subclass needs to create
|
||||
* an instance of TopicCache subclass with appropriate overrides for its
|
||||
* pure virtual functions, and pass this instance to IVersionControl's constructor.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \fn Core::IVersionControl::TopicCache::trackFile(const QString &repository)
|
||||
* Returns path to file that invalidates the cache when modified, for \a repository.
|
||||
* e.g. for git this file is .git/HEAD
|
||||
*
|
||||
* \fn Core::IVersionControl::TopicCache::refreshTopic(const QString &repository)
|
||||
* Returns current topic for \a repository.
|
||||
*/
|
||||
namespace Core {
|
||||
|
||||
QString IVersionControl::vcsOpenText() const
|
||||
@@ -41,9 +63,14 @@ QString IVersionControl::vcsMakeWritableText() const
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString IVersionControl::vcsTopic(const QString &)
|
||||
QString IVersionControl::vcsTopic(const QString &topLevel)
|
||||
{
|
||||
return QString();
|
||||
return m_topicCache ? m_topicCache->topic(topLevel) : QString();
|
||||
}
|
||||
|
||||
IVersionControl::~IVersionControl()
|
||||
{
|
||||
delete m_topicCache;
|
||||
}
|
||||
|
||||
IVersionControl::OpenSupportMode IVersionControl::openSupportMode(const QString &fileName) const
|
||||
@@ -52,6 +79,30 @@ IVersionControl::OpenSupportMode IVersionControl::openSupportMode(const QString
|
||||
return NoOpen;
|
||||
}
|
||||
|
||||
IVersionControl::TopicCache::~TopicCache()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns topic for repository under \a topLevel.
|
||||
*
|
||||
* If the cache for \a topLevel is valid, it will be used. Otherwise it will be refreshed.
|
||||
*/
|
||||
QString IVersionControl::TopicCache::topic(const QString &topLevel)
|
||||
{
|
||||
QTC_ASSERT(!topLevel.isEmpty(), return QString());
|
||||
TopicData &data = m_cache[topLevel];
|
||||
QString file = trackFile(topLevel);
|
||||
|
||||
if (file.isEmpty())
|
||||
return QString();
|
||||
const QDateTime lastModified = QFileInfo(file).lastModified();
|
||||
if (lastModified == data.timeStamp)
|
||||
return data.topic;
|
||||
data.timeStamp = lastModified;
|
||||
return data.topic = refreshTopic(topLevel);
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
#if defined(WITH_TESTS)
|
||||
|
||||
@@ -33,9 +33,10 @@
|
||||
#include "core_global.h"
|
||||
#include "id.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QFlags>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QFlags>
|
||||
|
||||
namespace Core {
|
||||
|
||||
@@ -64,8 +65,29 @@ public:
|
||||
OpenMandatory /*!< Files must always be opened by the VCS */
|
||||
};
|
||||
|
||||
IVersionControl() {}
|
||||
virtual ~IVersionControl() {}
|
||||
class TopicCache
|
||||
{
|
||||
public:
|
||||
virtual ~TopicCache();
|
||||
QString topic(const QString &topLevel);
|
||||
|
||||
protected:
|
||||
virtual QString trackFile(const QString &repository) = 0;
|
||||
virtual QString refreshTopic(const QString &repository) = 0;
|
||||
|
||||
private:
|
||||
struct TopicData
|
||||
{
|
||||
QDateTime timeStamp;
|
||||
QString topic;
|
||||
};
|
||||
|
||||
QHash<QString, TopicData> m_cache;
|
||||
|
||||
};
|
||||
|
||||
explicit IVersionControl(TopicCache *topicCache = 0) : m_topicCache(topicCache) {}
|
||||
virtual ~IVersionControl();
|
||||
|
||||
virtual QString displayName() const = 0;
|
||||
virtual Id id() const = 0;
|
||||
@@ -158,7 +180,7 @@ public:
|
||||
/*!
|
||||
* Topic (e.g. name of the current branch)
|
||||
*/
|
||||
virtual QString vcsTopic(const QString &directory);
|
||||
virtual QString vcsTopic(const QString &topLevel);
|
||||
|
||||
/*!
|
||||
* Display annotation for a file and scroll to line
|
||||
@@ -179,6 +201,9 @@ signals:
|
||||
void repositoryChanged(const QString &repository);
|
||||
void filesChanged(const QStringList &files);
|
||||
void configurationChanged();
|
||||
|
||||
private:
|
||||
TopicCache *m_topicCache;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Core::IVersionControl::SettingsFlags)
|
||||
|
||||
@@ -2024,28 +2024,13 @@ bool GitClient::synchronousHeadRefs(const QString &workingDirectory, QStringList
|
||||
return true;
|
||||
}
|
||||
|
||||
struct TopicData
|
||||
{
|
||||
QDateTime timeStamp;
|
||||
QString topic;
|
||||
};
|
||||
|
||||
// Retrieve topic (branch, tag or HEAD hash)
|
||||
QString GitClient::synchronousTopic(const QString &workingDirectory)
|
||||
{
|
||||
static QHash<QString, TopicData> topicCache;
|
||||
QString gitDir = findGitDirForRepository(workingDirectory);
|
||||
if (gitDir.isEmpty())
|
||||
return QString();
|
||||
TopicData &data = topicCache[gitDir];
|
||||
QDateTime lastModified = QFileInfo(gitDir + QLatin1String("/HEAD")).lastModified();
|
||||
if (lastModified == data.timeStamp)
|
||||
return data.topic;
|
||||
data.timeStamp = lastModified;
|
||||
// First try to find branch
|
||||
QString branch = synchronousCurrentLocalBranch(workingDirectory);
|
||||
if (!branch.isEmpty())
|
||||
return data.topic = branch;
|
||||
return branch;
|
||||
|
||||
// Detached HEAD, try a tag or remote branch
|
||||
QStringList references;
|
||||
@@ -2059,10 +2044,8 @@ QString GitClient::synchronousTopic(const QString &workingDirectory)
|
||||
|
||||
foreach (const QString &ref, references) {
|
||||
int derefInd = ref.indexOf(dereference);
|
||||
if (ref.startsWith(tagStart)) {
|
||||
return data.topic = ref.mid(tagStart.size(),
|
||||
(derefInd == -1) ? -1 : derefInd - tagStart.size());
|
||||
}
|
||||
if (ref.startsWith(tagStart))
|
||||
return ref.mid(tagStart.size(), (derefInd == -1) ? -1 : derefInd - tagStart.size());
|
||||
if (ref.startsWith(remoteStart)) {
|
||||
remoteBranch = ref.mid(remoteStart.size(),
|
||||
(derefInd == -1) ? -1 : derefInd - remoteStart.size());
|
||||
@@ -2070,7 +2053,7 @@ QString GitClient::synchronousTopic(const QString &workingDirectory)
|
||||
}
|
||||
|
||||
// No tag
|
||||
return data.topic = remoteBranch.isEmpty() ? tr("Detached HEAD") : remoteBranch;
|
||||
return remoteBranch.isEmpty() ? tr("Detached HEAD") : remoteBranch;
|
||||
}
|
||||
|
||||
bool GitClient::synchronousRevParseCmd(const QString &workingDirectory, const QString &ref,
|
||||
|
||||
@@ -38,7 +38,32 @@
|
||||
namespace Git {
|
||||
namespace Internal {
|
||||
|
||||
class GitTopicCache : public Core::IVersionControl::TopicCache
|
||||
{
|
||||
public:
|
||||
GitTopicCache(GitClient *client) :
|
||||
m_client(client)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
QString trackFile(const QString &repository)
|
||||
{
|
||||
const QString gitDir = m_client->findGitDirForRepository(repository);
|
||||
return gitDir.isEmpty() ? QString() : (gitDir + QLatin1String("/HEAD"));
|
||||
}
|
||||
|
||||
QString refreshTopic(const QString &repository)
|
||||
{
|
||||
return m_client->synchronousTopic(repository);
|
||||
}
|
||||
|
||||
private:
|
||||
GitClient *m_client;
|
||||
};
|
||||
|
||||
GitVersionControl::GitVersionControl(GitClient *client) :
|
||||
Core::IVersionControl(new GitTopicCache(client)),
|
||||
m_client(client)
|
||||
{
|
||||
}
|
||||
@@ -120,7 +145,7 @@ QString GitVersionControl::vcsGetRepositoryURL(const QString &directory)
|
||||
|
||||
QString GitVersionControl::vcsTopic(const QString &directory)
|
||||
{
|
||||
QString topic = m_client->synchronousTopic(directory);
|
||||
QString topic = Core::IVersionControl::vcsTopic(directory);
|
||||
const QString commandInProgress = m_client->commandInProgressDescription(directory);
|
||||
if (!commandInProgress.isEmpty())
|
||||
topic += QLatin1String(" (") + commandInProgress + QLatin1Char(')');
|
||||
|
||||
Reference in New Issue
Block a user