From b4b177fa27a084eef4e77df299987f9c90daab88 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Wed, 19 May 2010 17:41:14 +0200
Subject: [PATCH] VCS[git/hg]: Prevent search for repository from creating
 folders

... when autofs is involved. Check for files instead of folders
and stop checking/recursing up at '/' or $HOME. Further fixup
will follow.

Task-number: QTCREATORBUG-1361
Task-number: QTBUG-10495
---
 src/plugins/git/gitclient.cpp             | 11 +++----
 src/plugins/git/gitclient.h               |  3 --
 src/plugins/mercurial/mercurialclient.cpp | 13 +++-----
 src/plugins/vcsbase/vcsbaseplugin.cpp     | 36 ++++++++++++++++++++++-
 src/plugins/vcsbase/vcsbaseplugin.h       |  6 ++++
 5 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 8248d18d0d6..d613a604c8e 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 3f0d0dede7e..26423fce1d5 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 9a4bbabb856..ff78f0dc4bb 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 8cc60f0cfeb..7b1c3f40c1c 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 9574ee71b83..5d697fa3af9 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.
-- 
GitLab