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:
Friedemann Kleint
2009-12-08 14:26:41 +01:00
parent 8d6b4e51ab
commit 8097879d6d
31 changed files with 891 additions and 699 deletions

View File

@@ -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