diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 8248d18d0d6891ae7aa490d5378e13db7d87fb47..d613a604c8ea6960dcbc3c40f186f964c23084d5 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -52,6 +52,7 @@ #include <utils/synchronousprocess.h> #include <vcsbase/vcsbaseeditor.h> #include <vcsbase/vcsbaseoutputwindow.h> +#include <vcsbase/vcsbaseplugin.h> #include <projectexplorer/environment.h> @@ -155,13 +156,9 @@ const char *GitClient::noColorOption = "--no-color"; QString GitClient::findRepositoryForDirectory(const QString &dir) { - const QString gitDirectory = QLatin1String(kGitDirectoryC); - QDir directory(dir); - do { - if (QFileInfo(directory, gitDirectory).isDir()) - return directory.absolutePath(); - } while (directory.cdUp()); - return QString(); + // Check for ".git/config" + const QString checkFile = QLatin1String(kGitDirectoryC) + QLatin1String("/config"); + return VCSBase::VCSBasePlugin::findRepositoryForDirectory(dir, checkFile); } /* Create an editor associated to VCS output of a source file/directory diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 3f0d0dede7e1a01977d0b5515674e09eab8871e0..26423fce1d5bdc43d16f7ffce7a4ddfa41693764 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -72,9 +72,6 @@ public: explicit GitClient(GitPlugin *plugin); ~GitClient(); - bool managesDirectory(const QString &) const { return false; } - QString findTopLevelForDirectory(const QString &) const { return QString(); } - static QString findRepositoryForDirectory(const QString &dir); void diff(const QString &workingDirectory, const QStringList &diffArgs, const QString &fileName); diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 9a4bbabb85634210bb9bb8dfd87c783d1256350e..ff78f0dc4bb101d2e5bf818128172c066618e953 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -556,15 +556,10 @@ void MercurialClient::commit(const QString &repositoryRoot, const QStringList &f QString MercurialClient::findTopLevelForFile(const QFileInfo &file) { - const QString repositoryTopDir = QLatin1String(Constants::MECURIALREPO); - QDir dir = file.isDir() ? QDir(file.absoluteFilePath()) : QDir(file.absolutePath()); - - do { - if (QFileInfo(dir, repositoryTopDir).exists()) - return dir.absolutePath(); - } while (dir.cdUp()); - - return QString(); + const QString repositoryCheckFile = QLatin1String(Constants::MECURIALREPO) + QLatin1String("/requires"); + return file.isDir() ? + VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(), repositoryCheckFile) : + VCSBase::VCSBasePlugin::findRepositoryForDirectory(file.absolutePath(), repositoryCheckFile); } void MercurialClient::settingsChanged() diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 8cc60f0cfeb31fe8ee2cc6f3f8cc930bdb5f0798..7b1c3f40c1c3be467ed78692afdc2ab758fb0b1c 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -54,7 +54,7 @@ #include <QtGui/QFileDialog> #include <QtGui/QMainWindow> -enum { debug = 0 }; +enum { debug = 0, debugRepositorySearch = 0 }; namespace VCSBase { @@ -636,6 +636,40 @@ void VCSBasePlugin::slotTestRemoveSnapshot() d->m_testLastSnapshot.clear(); } +// Find top level for version controls like git/Mercurial that have +// a directory at the top of the repository. +// Note that checking for the existence of files is preferred over directories +// since checking for directories can cause them to be created when +// AutoFS is used (due its automatically creating mountpoints when querying +// a directory). In addition, bail out when reaching the home directory +// of the user or root (generally avoid '/', where mountpoints are created). +QString VCSBasePlugin::findRepositoryForDirectory(const QString &dirS, + const QString &checkFile) +{ + if (debugRepositorySearch) + qDebug() << ">VCSBasePlugin::findRepositoryForDirectory" << dirS << checkFile; + QTC_ASSERT(!dirS.isEmpty() && !checkFile.isEmpty(), return QString()); + + const QString root = QDir::rootPath(); + const QString home = QDir::homePath(); + + QDir directory(dirS); + do { + const QString absDirPath = directory.absolutePath(); + if (absDirPath == root || absDirPath == home) + break; + + if (QFileInfo(directory, checkFile).isFile()) { + if (debugRepositorySearch) + qDebug() << "<VCSBasePlugin::findRepositoryForDirectory> " << absDirPath; + return absDirPath; + } + } while (directory.cdUp()); + if (debugRepositorySearch) + qDebug() << "<VCSBasePlugin::findRepositoryForDirectory bailing out at " << directory.absolutePath(); + return QString(); +} + } // namespace VCSBase #include "vcsbaseplugin.moc" diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h index 9574ee71b8300ec0ee281b2625862424e8240ddc..5d697fa3af9dbdfde40f34975bd386b39be70ce9 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.h +++ b/src/plugins/vcsbase/vcsbaseplugin.h @@ -163,6 +163,12 @@ public: // For internal tests: Create actions driving IVersionControl's snapshot interface. QList<QAction*> createSnapShotTestActions(); + // Convenience that searches for the repository specifically for version control + // systems that do not have directories like "CVS" in each managed subdirectory + // but have a directory at the top of the repository like ".git" containing + // a well known file. See implementation for gory details. + static QString findRepositoryForDirectory(const QString &dir, const QString &checkFile); + public slots: // Convenience slot for "Delete current file" action. Prompts to // delete the file via VCSManager.