forked from qt-creator/qt-creator
VCS: Introduce Base class for VCS plugins, use in git.
Fixes: - Cannot diff a file that does not belong to a project - Cannot commit when a temporary diff/log view is open due to the current file pointing to a temporary directory - git's project-related actions not passing the correct relative path. Implementation: - Centralize code to listen for Qt Creator's relevant state changes in VCSBasePlugin, dispatching the changes to the instances affected. (avoiding multiple invocations of searches/QFileInfo on current). - Do the same for the corelistener catching closing SubmitEditors. - Introduce VCSBasePluginState representing the relevant state (current file/project). - Call git with working directory set and relative arguments - Remove setEnabled/isEnabled() logic of IVersionControl - Pass toplevel from VCSManager to avoid duplicate searches.
This commit is contained in:
@@ -46,15 +46,18 @@ enum { debug = 0 };
|
||||
namespace Core {
|
||||
|
||||
typedef QList<IVersionControl *> VersionControlList;
|
||||
typedef QMap<QString, IVersionControl *> VersionControlCache;
|
||||
|
||||
static inline VersionControlList allVersionControls()
|
||||
{
|
||||
return ExtensionSystem::PluginManager::instance()->getObjects<IVersionControl>();
|
||||
}
|
||||
|
||||
// ---- VCSManagerPrivate
|
||||
// ---- VCSManagerPrivate:
|
||||
// Maintains a cache of top-level directory->version control.
|
||||
|
||||
struct VCSManagerPrivate {
|
||||
QMap<QString, IVersionControl *> m_cachedMatches;
|
||||
VersionControlCache m_cachedMatches;
|
||||
};
|
||||
|
||||
VCSManager::VCSManager(QObject *parent) :
|
||||
@@ -79,57 +82,48 @@ void VCSManager::extensionsInitialized()
|
||||
}
|
||||
}
|
||||
|
||||
void VCSManager::setVCSEnabled(const QString &directory)
|
||||
IVersionControl* VCSManager::findVersionControlForDirectory(const QString &directory,
|
||||
QString *topLevelDirectory)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << directory;
|
||||
IVersionControl* managingVCS = findVersionControlForDirectory(directory);
|
||||
const VersionControlList versionControls = allVersionControls();
|
||||
foreach (IVersionControl *versionControl, versionControls) {
|
||||
const bool newEnabled = versionControl == managingVCS;
|
||||
if (newEnabled != versionControl->isEnabled())
|
||||
versionControl->setEnabled(newEnabled);
|
||||
}
|
||||
}
|
||||
typedef VersionControlCache::const_iterator VersionControlCacheConstIterator;
|
||||
const VersionControlCacheConstIterator cacheEnd = m_d->m_cachedMatches.constEnd();
|
||||
|
||||
void VCSManager::setAllVCSEnabled()
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
const VersionControlList versionControls = allVersionControls();
|
||||
foreach (IVersionControl *versionControl, versionControls)
|
||||
if (!versionControl->isEnabled())
|
||||
versionControl->setEnabled(true);
|
||||
}
|
||||
if (topLevelDirectory)
|
||||
topLevelDirectory->clear();
|
||||
|
||||
IVersionControl* VCSManager::findVersionControlForDirectory(const QString &directory)
|
||||
{
|
||||
// first look into the cache, check the whole name
|
||||
|
||||
{
|
||||
const QMap<QString, IVersionControl *>::const_iterator it = m_d->m_cachedMatches.constFind(directory);
|
||||
if (it != m_d->m_cachedMatches.constEnd())
|
||||
return it.value();
|
||||
// First check if the directory has an entry, meaning it is a top level
|
||||
const VersionControlCacheConstIterator fullPathIt = m_d->m_cachedMatches.constFind(directory);
|
||||
if (fullPathIt != cacheEnd) {
|
||||
if (topLevelDirectory)
|
||||
*topLevelDirectory = directory;
|
||||
return fullPathIt.value();
|
||||
}
|
||||
|
||||
// Split the path, starting from top, try to find the matching repository
|
||||
int pos = 0;
|
||||
const QChar slash = QLatin1Char('/');
|
||||
while (true) {
|
||||
int index = directory.indexOf(slash, pos);
|
||||
const int index = directory.indexOf(slash, pos);
|
||||
if (index == -1)
|
||||
break;
|
||||
const QString directoryPart = directory.left(index);
|
||||
QMap<QString, IVersionControl *>::const_iterator it = m_d->m_cachedMatches.constFind(directoryPart);
|
||||
if (it != m_d->m_cachedMatches.constEnd())
|
||||
const VersionControlCacheConstIterator it = m_d->m_cachedMatches.constFind(directoryPart);
|
||||
if (it != cacheEnd) {
|
||||
if (topLevelDirectory)
|
||||
*topLevelDirectory = it.key();
|
||||
return it.value();
|
||||
pos = index+1;
|
||||
}
|
||||
pos = index + 1;
|
||||
}
|
||||
|
||||
// ah nothing so ask the IVersionControls directly
|
||||
// Nothing: ask the IVersionControls directly, insert the toplevel into the cache.
|
||||
const VersionControlList versionControls = allVersionControls();
|
||||
foreach (IVersionControl * versionControl, versionControls) {
|
||||
if (versionControl->managesDirectory(directory)) {
|
||||
m_d->m_cachedMatches.insert(versionControl->findTopLevelForDirectory(directory), versionControl);
|
||||
const QString topLevel = versionControl->findTopLevelForDirectory(directory);
|
||||
m_d->m_cachedMatches.insert(topLevel, versionControl);
|
||||
if (topLevelDirectory)
|
||||
*topLevelDirectory = topLevel;
|
||||
return versionControl;
|
||||
}
|
||||
}
|
||||
@@ -152,4 +146,14 @@ bool VCSManager::showDeleteDialog(const QString &fileName)
|
||||
return vc->vcsDelete(fileName);
|
||||
}
|
||||
|
||||
CORE_EXPORT QDebug operator<<(QDebug in, const VCSManager &v)
|
||||
{
|
||||
QDebug nospace = in.nospace();
|
||||
const VersionControlCache::const_iterator cend = v.m_d->m_cachedMatches.constEnd();
|
||||
for (VersionControlCache::const_iterator it = v.m_d->m_cachedMatches.constBegin(); it != cend; ++it)
|
||||
nospace << "Directory: " << it.key() << ' ' << it.value()->name() << '\n';
|
||||
nospace << '\n';
|
||||
return in;
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
Reference in New Issue
Block a user