diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h index 8fe0bc038e0c9cf290ce4865f2652bffad5aa608..0cd29f9438865aa00b2d8b63a4e7ec880af8f60d 100644 --- a/src/plugins/coreplugin/iversioncontrol.h +++ b/src/plugins/coreplugin/iversioncontrol.h @@ -56,21 +56,12 @@ public: /*! * Returns whether files in this directory should be managed with this * version control. + * If \a topLevel is non-null, it should return the topmost directory, + * for which this IVersionControl should be used. The VCSManager assumes + * that all files in the returned directory are managed by the same IVersionControl. */ - virtual bool managesDirectory(const QString &filename) const = 0; - /*! - * This function should return the topmost directory, for which this - * IVersionControl should be used. The VCSManager assumes that all files in - * the returned directory are managed by the same IVersionControl. - * - * Note that this is used as an optimization, so that the VCSManager - * doesn't need to call managesDirectory(..) for each directory. - * - * This function is called after finding out that the directory is managed - * by a specific version control. - */ - virtual QString findTopLevelForDirectory(const QString &directory) const = 0; + virtual bool managesDirectory(const QString &filename, QString *topLevel = 0) const = 0; /*! * Called to query whether a VCS supports the respective operations. diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp index 35d5b2f0644560c79e40cfbf53044aea8b6d5fbd..0221e29c9fa2a4ecf401fe67045da5fd60bcfa1e 100644 --- a/src/plugins/coreplugin/vcsmanager.cpp +++ b/src/plugins/coreplugin/vcsmanager.cpp @@ -90,6 +90,18 @@ IVersionControl* VCSManager::findVersionControlForDirectory(const QString &direc QString *topLevelDirectory) { typedef VersionControlCache::const_iterator VersionControlCacheConstIterator; + + if (debug) { + qDebug(">findVersionControlForDirectory %s topLevelPtr %d", + qPrintable(directory), (topLevelDirectory != 0)); + if (debug > 1) { + const VersionControlCacheConstIterator cend = m_d->m_cachedMatches.constEnd(); + for (VersionControlCacheConstIterator it = m_d->m_cachedMatches.constBegin(); it != cend; ++it) + qDebug("Cache %s -> '%s'", qPrintable(it.key()), qPrintable(it.value()->displayName())); + } + } + QTC_ASSERT(!directory.isEmpty(), return 0); + const VersionControlCacheConstIterator cacheEnd = m_d->m_cachedMatches.constEnd(); if (topLevelDirectory) @@ -100,37 +112,51 @@ IVersionControl* VCSManager::findVersionControlForDirectory(const QString &direc if (fullPathIt != cacheEnd) { if (topLevelDirectory) *topLevelDirectory = directory; + if (debug) + qDebug("<findVersionControlForDirectory: full cache match for VCS '%s'", qPrintable(fullPathIt.value()->displayName())); return fullPathIt.value(); } - // Split the path, starting from top, try to find the matching repository - int pos = 0; + // Split the path, trying to find the matching repository. We start from the reverse + // in order to detected nested repositories correctly (say, a git checkout under SVN). + // Note that detection of a nested version control will still fail if the + // above-located version control is detected and entered into the cache first. + // The nested one can then no longer be found due to the splitting of the paths. + int pos = directory.size() - 1; const QChar slash = QLatin1Char('/'); while (true) { - const int index = directory.indexOf(slash, pos); - if (index == -1) + const int index = directory.lastIndexOf(slash, pos); + if (index <= 0) // Stop at '/' or not found break; const QString directoryPart = directory.left(index); const VersionControlCacheConstIterator it = m_d->m_cachedMatches.constFind(directoryPart); if (it != cacheEnd) { if (topLevelDirectory) *topLevelDirectory = it.key(); + if (debug) + qDebug("<findVersionControlForDirectory: cache match for VCS '%s', topLevel: %s", + qPrintable(it.value()->displayName()), qPrintable(it.key())); return it.value(); } - pos = index + 1; + pos = index - 1; } // Nothing: ask the IVersionControls directly, insert the toplevel into the cache. const VersionControlList versionControls = allVersionControls(); foreach (IVersionControl * versionControl, versionControls) { - if (versionControl->managesDirectory(directory)) { - const QString topLevel = versionControl->findTopLevelForDirectory(directory); + QString topLevel; + if (versionControl->managesDirectory(directory, &topLevel)) { m_d->m_cachedMatches.insert(topLevel, versionControl); if (topLevelDirectory) *topLevelDirectory = topLevel; + if (debug) + qDebug("<findVersionControlForDirectory: invocation of '%s' matches: %s", + qPrintable(versionControl->displayName()), qPrintable(topLevel)); return versionControl; } } + if (debug) + qDebug("<findVersionControlForDirectory: No match for %s", qPrintable(directory)); return 0; } diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp index 42462006dfd3b62698822a1abbf06562c9bfd1f9..dbf8adf4b78c8dc8b25add6fe6b0600cd9a59deb 100644 --- a/src/plugins/cvs/cvscontrol.cpp +++ b/src/plugins/cvs/cvscontrol.cpp @@ -120,14 +120,9 @@ bool CVSControl::vcsAnnotate(const QString &file, int line) return true; } -bool CVSControl::managesDirectory(const QString &directory) const +bool CVSControl::managesDirectory(const QString &directory, QString *topLevel) const { - return m_plugin->managesDirectory(directory); -} - -QString CVSControl::findTopLevelForDirectory(const QString &directory) const -{ - return m_plugin->findTopLevelForDirectory(directory); + return m_plugin->managesDirectory(directory, topLevel); } void CVSControl::emitRepositoryChanged(const QString &s) diff --git a/src/plugins/cvs/cvscontrol.h b/src/plugins/cvs/cvscontrol.h index 38a8ccfe8e73c669d8e7087a1fa9b7648dc4a3b4..4fd06c2de72d1be2df14d4c1474048d3a0aece31 100644 --- a/src/plugins/cvs/cvscontrol.h +++ b/src/plugins/cvs/cvscontrol.h @@ -45,8 +45,7 @@ public: explicit CVSControl(CVSPlugin *plugin); virtual QString displayName() const; - virtual bool managesDirectory(const QString &directory) const; - virtual QString findTopLevelForDirectory(const QString &directory) const; + virtual bool managesDirectory(const QString &directory, QString *topLevel = 0) const; virtual bool supportsOperation(Operation operation) const; virtual bool vcsOpen(const QString &fileName); diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index 1f7e646fe1d91c8568898817b50dc6e3826fcbe4..1bdb606be6b1cc2071c2f379a57dd484be06d796 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -827,8 +827,10 @@ void CVSPlugin::slotDescribe(const QString &source, const QString &changeNr) bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString *errorMessage) { - const QString toplevel = findTopLevelForDirectory(QFileInfo(file).absolutePath()); - if (toplevel.isEmpty()) { + + QString toplevel; + const bool manages = managesDirectory(QFileInfo(file).absolutePath(), &toplevel); + if (!manages || toplevel.isEmpty()) { *errorMessage = msgCannotFindTopLevel(file); return false; } @@ -1122,45 +1124,44 @@ bool CVSPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName) /* CVS has a "CVS" directory in each directory it manages. The top level * is the first directory under the directory that does not have it. */ -bool CVSPlugin::managesDirectory(const QString &directory) const +bool CVSPlugin::managesDirectory(const QString &directory, QString *topLevel /* = 0 */) const { + if (topLevel) + topLevel->clear(); + bool manages = false; const QDir dir(directory); - const bool rc = dir.exists() && managesDirectory(dir); - if (CVS::Constants::debug) - qDebug() << "CVSPlugin::managesDirectory" << directory << rc; - return rc; + do { + if (!dir.exists() || !checkCVSDirectory(dir)) + break; + manages = true; + if (!topLevel) + break; + /* Recursing up, the top level is a child of the first directory that does + * not have a "CVS" directory. The starting directory must be a managed + * one. Go up and try to find the first unmanaged parent dir. */ + QDir lastDirectory = dir; + for (QDir parentDir = lastDirectory; parentDir.cdUp() ; lastDirectory = parentDir) { + if (!checkCVSDirectory(parentDir)) { + *topLevel = lastDirectory.absolutePath(); + break; + } + } + } while (false); + if (CVS::Constants::debug) { + QDebug nsp = qDebug().nospace(); + nsp << "CVSPlugin::managesDirectory" << directory << manages; + if (topLevel) + nsp << *topLevel; + } + return manages; } -bool CVSPlugin::managesDirectory(const QDir &directory) const +bool CVSPlugin::checkCVSDirectory(const QDir &directory) const { const QString cvsDir = directory.absoluteFilePath(QLatin1String("CVS")); return QFileInfo(cvsDir).isDir(); } -QString CVSPlugin::findTopLevelForDirectory(const QString &directory) const -{ - // Debug wrapper - const QString rc = findTopLevelForDirectoryI(directory); - if (CVS::Constants::debug) - qDebug() << "CVSPlugin::findTopLevelForDirectory" << directory << rc; - return rc; -} - -QString CVSPlugin::findTopLevelForDirectoryI(const QString &directory) const -{ - /* Recursing up, the top level is a child of the first directory that does - * not have a "CVS" directory. The starting directory must be a managed - * one. Go up and try to find the first unmanaged parent dir. */ - QDir lastDirectory = QDir(directory); - if (!lastDirectory.exists() || !managesDirectory(lastDirectory)) - return QString(); - for (QDir parentDir = lastDirectory; parentDir.cdUp() ; lastDirectory = parentDir) { - if (!managesDirectory(parentDir)) - return lastDirectory.absolutePath(); - } - return QString(); -} - CVSControl *CVSPlugin::cvsVersionControl() const { return static_cast<CVSControl *>(versionControl()); diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h index 1548729dff11016524e3278650d2be5c54d81bad..c95cb8369f9dc453be65a68ed1c858ddc992fbff 100644 --- a/src/plugins/cvs/cvsplugin.h +++ b/src/plugins/cvs/cvsplugin.h @@ -95,8 +95,7 @@ public: // IVersionControl bool vcsAdd(const QString &workingDir, const QString &fileName); bool vcsDelete(const QString &workingDir, const QString &fileName); - bool managesDirectory(const QString &directory) const; - QString findTopLevelForDirectory(const QString &directory) const; + bool managesDirectory(const QString &directory, QString *topLevel = 0) const; static CVSPlugin *cvsPluginInstance(); @@ -145,7 +144,7 @@ private: void filelog(const QString &workingDir, const QStringList &files = QStringList(), bool enableAnnotationContextMenu = false); - bool managesDirectory(const QDir &directory) const; + bool checkCVSDirectory(const QDir &directory) const; QString findTopLevelForDirectoryI(const QString &directory) const; void startCommit(const QString &workingDir, const QStringList &files = QStringList()); bool commit(const QString &messageFile, const QStringList &subVersionFileList); diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp index 65a46e492e1f701d8fc23810c491114345e6e3ee..370e20bb2704a1ab835183519f4e09126f6a290c 100644 --- a/src/plugins/git/gitversioncontrol.cpp +++ b/src/plugins/git/gitversioncontrol.cpp @@ -206,14 +206,12 @@ bool GitVersionControl::vcsRemoveSnapshot(const QString &topLevel, const QString && gitClient()->synchronousStashRemove(topLevel, stashName); } -bool GitVersionControl::managesDirectory(const QString &directory) const +bool GitVersionControl::managesDirectory(const QString &directory, QString *topLevel) const { - return !GitClient::findRepositoryForDirectory(directory).isEmpty(); -} - -QString GitVersionControl::findTopLevelForDirectory(const QString &directory) const -{ - return GitClient::findRepositoryForDirectory(directory); + const QString topLevelFound = GitClient::findRepositoryForDirectory(directory); + if (topLevel) + *topLevel = topLevelFound; + return !topLevelFound.isEmpty(); } bool GitVersionControl::vcsAnnotate(const QString &file, int line) diff --git a/src/plugins/git/gitversioncontrol.h b/src/plugins/git/gitversioncontrol.h index 098d8bef5282e2922f4c7891f41dc5317b0b618a..35504747a7ca3ecf284cca76ec081b85ee369ca8 100644 --- a/src/plugins/git/gitversioncontrol.h +++ b/src/plugins/git/gitversioncontrol.h @@ -46,8 +46,7 @@ public: virtual QString displayName() const; - bool managesDirectory(const QString &directory) const; - virtual QString findTopLevelForDirectory(const QString &directory) const; + virtual bool managesDirectory(const QString &directory, QString *topLevel) const; virtual bool supportsOperation(Operation operation) const; virtual bool vcsOpen(const QString &fileName); diff --git a/src/plugins/mercurial/mercurialcontrol.cpp b/src/plugins/mercurial/mercurialcontrol.cpp index e8cf97e1fbd25d241c96f360f18e2d980319f244..61342dc3507b8505d16ff887b6a8c9352c248842 100644 --- a/src/plugins/mercurial/mercurialcontrol.cpp +++ b/src/plugins/mercurial/mercurialcontrol.cpp @@ -47,16 +47,13 @@ QString MercurialControl::displayName() const return tr("Mercurial"); } -bool MercurialControl::managesDirectory(const QString &directory) const +bool MercurialControl::managesDirectory(const QString &directory, QString *topLevel) const { QFileInfo dir(directory); - return !mercurialClient->findTopLevelForFile(dir).isEmpty(); -} - -QString MercurialControl::findTopLevelForDirectory(const QString &directory) const -{ - QFileInfo dir(directory); - return mercurialClient->findTopLevelForFile(dir); + const QString topLevelFound = mercurialClient->findTopLevelForFile(dir); + if (topLevel) + *topLevel = topLevelFound; + return !topLevelFound.isEmpty(); } bool MercurialControl::supportsOperation(Operation operation) const @@ -137,8 +134,9 @@ bool MercurialControl::vcsAnnotate(const QString &file, int line) bool MercurialControl::sccManaged(const QString &filename) { const QFileInfo fi(filename); - const QString topLevel = findTopLevelForDirectory(fi.absolutePath()); - if (topLevel.isEmpty()) + QString topLevel; + const bool managed = managesDirectory(fi.absolutePath(), &topLevel); + if (!managed || topLevel.isEmpty()) return false; const QDir topLevelDir(topLevel); return mercurialClient->manifestSync(topLevel, topLevelDir.relativeFilePath(filename)); diff --git a/src/plugins/mercurial/mercurialcontrol.h b/src/plugins/mercurial/mercurialcontrol.h index 02be0951bbc16cba7dfa51d66eea3b9c919bbe62..b74fce99ff8fa4a1e53a7c74d0178d8dd5dacfa9 100644 --- a/src/plugins/mercurial/mercurialcontrol.h +++ b/src/plugins/mercurial/mercurialcontrol.h @@ -50,8 +50,7 @@ public: explicit MercurialControl(MercurialClient *mercurialClient); QString displayName() const; - bool managesDirectory(const QString &filename) const; - QString findTopLevelForDirectory(const QString &directory) const; + bool managesDirectory(const QString &filename, QString *topLevel = 0) const; bool supportsOperation(Operation operation) const; bool vcsOpen(const QString &fileName); bool vcsAdd(const QString &filename); diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index fefa63b675674f4ce7011bdba8b43d43afd1b471..4a44dc43a5021ac6b8fadddc0f50efdf8dc91bc9 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -848,7 +848,20 @@ void PerforcePlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) m_updateAllAction->setEnabled(true); } -bool PerforcePlugin::managesDirectory(const QString &directory) +bool PerforcePlugin::managesDirectory(const QString &directory, QString *topLevel /* = 0 */) +{ + const bool rc = managesDirectoryFstat(directory); + if (topLevel) { + if (rc) { + *topLevel = m_settings.topLevelSymLinkTarget(); + } else { + topLevel->clear(); + } + } + return rc; +} + +bool PerforcePlugin::managesDirectoryFstat(const QString &directory) { if (!m_settings.isValid()) return false; @@ -875,13 +888,6 @@ bool PerforcePlugin::managesDirectory(const QString &directory) return managed; } -QString PerforcePlugin::findTopLevelForDirectory(const QString &dir) -{ - if (!m_settings.isValid()) - return QString(); - return managesDirectory(dir) ? m_settings.topLevelSymLinkTarget() : QString(); -} - bool PerforcePlugin::vcsOpen(const QString &workingDir, const QString &fileName) { if (Perforce::Constants::debug) diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h index feddd2bcf6ae883673fc78a700a3a7eda429945b..1e9cceb3ab50d99320cdb0d992b95099f89417b5 100644 --- a/src/plugins/perforce/perforceplugin.h +++ b/src/plugins/perforce/perforceplugin.h @@ -84,8 +84,7 @@ public: bool initialize(const QStringList &arguments, QString *error_message); void extensionsInitialized(); - bool managesDirectory(const QString &directory); - QString findTopLevelForDirectory(const QString &directory); + bool managesDirectory(const QString &directory, QString *topLevel = 0); bool vcsOpen(const QString &workingDir, const QString &fileName); bool vcsAdd(const QString &workingDir, const QString &fileName); bool vcsDelete(const QString &workingDir, const QString &filename); @@ -194,6 +193,7 @@ private: void updateCheckout(const QString &workingDir = QString(), const QStringList &dirs = QStringList()); bool revertProject(const QString &workingDir, const QStringList &args, bool unchangedOnly); + bool managesDirectoryFstat(const QString &directory); inline PerforceVersionControl *perforceVersionControl() const; diff --git a/src/plugins/perforce/perforceversioncontrol.cpp b/src/plugins/perforce/perforceversioncontrol.cpp index e715fa7ec8ace316c10b545ccdae4e366a7f1489..2dc414f59cdb2eca4dbfa74a55436e0c224766de 100644 --- a/src/plugins/perforce/perforceversioncontrol.cpp +++ b/src/plugins/perforce/perforceversioncontrol.cpp @@ -120,19 +120,15 @@ bool PerforceVersionControl::vcsAnnotate(const QString &file, int line) return true; } -bool PerforceVersionControl::managesDirectory(const QString &directory) const -{ - const bool rc = m_plugin->managesDirectory(directory); - if (Perforce::Constants::debug) - qDebug() << "managesDirectory" << directory << rc; - return rc; -} - -QString PerforceVersionControl::findTopLevelForDirectory(const QString &directory) const -{ - const QString rc = m_plugin->findTopLevelForDirectory(directory); - if (Perforce::Constants::debug) - qDebug() << "findTopLevelForDirectory" << directory << rc; +bool PerforceVersionControl::managesDirectory(const QString &directory, QString *topLevel) const +{ + const bool rc = m_plugin->managesDirectory(directory, topLevel); + if (Perforce::Constants::debug) { + QDebug nsp = qDebug().nospace(); + nsp << "managesDirectory" << directory << rc; + if (topLevel) + nsp << topLevel; + } return rc; } diff --git a/src/plugins/perforce/perforceversioncontrol.h b/src/plugins/perforce/perforceversioncontrol.h index 9fe43af676c1b573e58c4c23953bfede19882098..1e14cd2810f2820b1a54ae91ca685afe22b5334a 100644 --- a/src/plugins/perforce/perforceversioncontrol.h +++ b/src/plugins/perforce/perforceversioncontrol.h @@ -45,8 +45,8 @@ public: virtual QString displayName() const; - bool managesDirectory(const QString &directory) const; - virtual QString findTopLevelForDirectory(const QString &directory) const; + virtual bool managesDirectory(const QString &directory, QString *topLevel = 0) const; + virtual bool supportsOperation(Operation operation) const; virtual bool vcsOpen(const QString &fileName); diff --git a/src/plugins/subversion/subversioncontrol.cpp b/src/plugins/subversion/subversioncontrol.cpp index f7b4648dcb8f797899687f66f758a0a4d47473d2..f25fc3ab6a2b70ab19357c812024ea7d006523c4 100644 --- a/src/plugins/subversion/subversioncontrol.cpp +++ b/src/plugins/subversion/subversioncontrol.cpp @@ -114,14 +114,9 @@ bool SubversionControl::vcsRemoveSnapshot(const QString &, const QString &) return false; } -bool SubversionControl::managesDirectory(const QString &directory) const +bool SubversionControl::managesDirectory(const QString &directory, QString *topLevel) const { - return m_plugin->managesDirectory(directory); -} - -QString SubversionControl::findTopLevelForDirectory(const QString &directory) const -{ - return m_plugin->findTopLevelForDirectory(directory); + return m_plugin->managesDirectory(directory, topLevel); } bool SubversionControl::vcsAnnotate(const QString &file, int line) diff --git a/src/plugins/subversion/subversioncontrol.h b/src/plugins/subversion/subversioncontrol.h index 8389f822495ca6d2ee79a40d26ed537ca52ad96b..5610059d66168f974686d10817e0a18b8cab03c1 100644 --- a/src/plugins/subversion/subversioncontrol.h +++ b/src/plugins/subversion/subversioncontrol.h @@ -45,8 +45,7 @@ public: explicit SubversionControl(SubversionPlugin *plugin); virtual QString displayName() const; - virtual bool managesDirectory(const QString &directory) const; - virtual QString findTopLevelForDirectory(const QString &directory) const; + virtual bool managesDirectory(const QString &directory, QString *topLevel = 0) const; virtual bool supportsOperation(Operation operation) const; virtual bool vcsOpen(const QString &fileName); diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 857bad4731368132e3dd07341e5fb8f7bb2571b9..ff299b1912903f0c62e29bee9f7db3cad34d8dc7 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -940,8 +940,9 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr) // To describe a complete change, find the top level and then do //svn diff -r 472958:472959 <top level> const QFileInfo fi(source); - const QString topLevel = findTopLevelForDirectory(fi.isDir() ? source : fi.absolutePath()); - if (topLevel.isEmpty()) + QString topLevel; + const bool manages = managesDirectory(fi.isDir() ? source : fi.absolutePath(), &topLevel); + if (!manages || topLevel.isEmpty()) return; if (Subversion::Constants::debug) qDebug() << Q_FUNC_INFO << source << topLevel << changeNr; @@ -1184,7 +1185,7 @@ bool SubversionPlugin::vcsAdd14(const QString &workingDir, const QString &rawFil if (!path.isEmpty()) path += slash; path += relativePath.at(p); - if (!managesDirectory(QDir(path))) { + if (!checkSVNSubDir(QDir(path))) { QStringList addDirArgs; addDirArgs << QLatin1String("add") << QLatin1String("--non-recursive") << QDir::toNativeSeparators(path); const SubversionResponse addDirResponse = runSvn(workingDir, addDirArgs, m_settings.timeOutMS(), true); @@ -1224,16 +1225,40 @@ bool SubversionPlugin::vcsMove(const QString &workingDir, const QString &from, c /* Subversion has ".svn" directory in each directory * it manages. The top level is the first directory * under the directory that does not have a ".svn". */ -bool SubversionPlugin::managesDirectory(const QString &directory) const +bool SubversionPlugin::managesDirectory(const QString &directory, QString *topLevel /* = 0 */) const { const QDir dir(directory); - const bool rc = dir.exists() && managesDirectory(dir); - if (Subversion::Constants::debug) - qDebug() << "SubversionPlugin::managesDirectory" << directory << rc; - return rc; + if (topLevel) + topLevel->clear(); + bool manages = false; + do { + if (!dir.exists() || !checkSVNSubDir(dir)) + break; + manages = true; + if (!topLevel) + break; + /* Recursing up, the top level is a child of the first directory that does + * not have a ".svn" directory. The starting directory must be a managed + * one. Go up and try to find the first unmanaged parent dir. */ + QDir lastDirectory = dir; + for (QDir parentDir = lastDirectory; parentDir.cdUp() ; lastDirectory = parentDir) { + if (!checkSVNSubDir(parentDir)) { + *topLevel = lastDirectory.absolutePath(); + break; + } + } + } while (false); + if (Subversion::Constants::debug) { + QDebug nsp = qDebug().nospace(); + nsp << "SubversionPlugin::managesDirectory" << directory << manages; + if (topLevel) + nsp << *topLevel; + } + return manages; } -bool SubversionPlugin::managesDirectory(const QDir &directory) const +// Check whether SVN management subdirs exist. +bool SubversionPlugin::checkSVNSubDir(const QDir &directory) const { const int dirCount = m_svnDirectories.size(); for (int i = 0; i < dirCount; i++) { @@ -1244,30 +1269,6 @@ bool SubversionPlugin::managesDirectory(const QDir &directory) const return false; } -QString SubversionPlugin::findTopLevelForDirectory(const QString &directory) const -{ - // Debug wrapper - const QString rc = findTopLevelForDirectoryI(directory); - if (Subversion::Constants::debug) - qDebug() << "SubversionPlugin::findTopLevelForDirectory" << directory << rc; - return rc; -} - -QString SubversionPlugin::findTopLevelForDirectoryI(const QString &directory) const -{ - /* Recursing up, the top level is a child of the first directory that does - * not have a ".svn" directory. The starting directory must be a managed - * one. Go up and try to find the first unmanaged parent dir. */ - QDir lastDirectory = QDir(directory); - if (!lastDirectory.exists() || !managesDirectory(lastDirectory)) - return QString(); - for (QDir parentDir = lastDirectory; parentDir.cdUp() ; lastDirectory = parentDir) { - if (!managesDirectory(parentDir)) - return lastDirectory.absolutePath(); - } - return QString(); -} - SubversionControl *SubversionPlugin::subVersionControl() const { return static_cast<SubversionControl *>(versionControl()); diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h index a7bb187c56d44f2b95546d1414a246ab6d3671e3..278cb2d30336041a64d82d34a60fcb337594c430 100644 --- a/src/plugins/subversion/subversionplugin.h +++ b/src/plugins/subversion/subversionplugin.h @@ -95,8 +95,7 @@ public: bool vcsAdd15(const QString &workingDir, const QString &fileName); bool vcsDelete(const QString &workingDir, const QString &fileName); bool vcsMove(const QString &workingDir, const QString &from, const QString &to); - bool managesDirectory(const QString &directory) const; - QString findTopLevelForDirectory(const QString &directory) const; + bool managesDirectory(const QString &directory, QString *topLevel = 0) const; static SubversionPlugin *subversionPluginInstance(); @@ -145,8 +144,7 @@ private: bool enableAnnotationContextMenu = false); void svnStatus(const QString &workingDir, const QStringList &relativePath = QStringList()); void svnUpdate(const QString &workingDir, const QStringList &relativePaths = QStringList()); - bool managesDirectory(const QDir &directory) const; - QString findTopLevelForDirectoryI(const QString &directory) const; + bool checkSVNSubDir(const QDir &directory) const; void startCommit(const QString &workingDir, const QStringList &files = QStringList()); bool commit(const QString &messageFile, const QStringList &subVersionFileList); void cleanCommitMessageFile(); diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index 67b3e80901bc4ff33952fdba91284d45d929e3bd..815a062247577e3b54652e266ee1d4ad800c99b4 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -821,8 +821,8 @@ QString VCSBaseEditor::findDiffFile(const QString &f, Core::IVersionControl *con // Try to locate via repository. if (!control) return QString(); - const QString topLevel = control->findTopLevelForDirectory(sourceDir); - if (topLevel.isEmpty()) + QString topLevel; + if (!control->managesDirectory(sourceDir, &topLevel)) return QString(); const QFileInfo topLevelFileInfo(topLevel + slash + f); if (topLevelFileInfo.isFile())