From 86d7e28db4053d771fba2819d88ffbf5cf0843e5 Mon Sep 17 00:00:00 2001
From: Petar Perisin <petar.perisin@gmail.com>
Date: Fri, 26 Apr 2013 00:00:30 +0200
Subject: [PATCH] Git - added submoduleDataMap to handle submodule data

Change-Id: I8462ed07f3d1edce5c7f5ab8c166ce8c68b6d4b3
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
---
 src/plugins/git/gerrit/gerritplugin.cpp | 16 +++----
 src/plugins/git/gitclient.cpp           | 60 ++++++++++++++++++++-----
 src/plugins/git/gitclient.h             | 12 ++++-
 src/plugins/git/gitplugin.cpp           |  3 +-
 4 files changed, 69 insertions(+), 22 deletions(-)

diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp
index 71637952f00..c1687fb7971 100644
--- a/src/plugins/git/gerrit/gerritplugin.cpp
+++ b/src/plugins/git/gerrit/gerritplugin.cpp
@@ -511,21 +511,19 @@ void GerritPlugin::fetch(const QSharedPointer<Gerrit::Internal::GerritChange> &c
                 }
             }
 
-            if (!verifiedRepository && QFile::exists(repository + QLatin1String("/.gitmodules"))) {
-                QMap<QString,QString> submodules = gitClient->synchronousSubmoduleList(repository);
-
-                QMap<QString,QString>::const_iterator i = submodules.constBegin();
-                while (i != submodules.constEnd()) {
-                    QString remote = i.value();
+            if (!verifiedRepository) {
+                Git::Internal::SubmoduleDataMap submodules = gitClient->submoduleList(repository);
+                foreach (const Git::Internal::SubmoduleData &submoduleData, submodules) {
+                    QString remote = submoduleData.url;
                     if (remote.endsWith(QLatin1String(".git")))
                         remote.chop(4);
                     if (remote.contains(m_parameters->host) && remote.endsWith(change->project)
-                            && QFile::exists(repository + QLatin1Char('/') + i.key())) {
-                        repository = QDir::cleanPath(repository + QLatin1Char('/') + i.key());
+                            && QFile::exists(repository + QLatin1Char('/') + submoduleData.dir)) {
+                        repository = QDir::cleanPath(repository + QLatin1Char('/')
+                                                     + submoduleData.dir);
                         verifiedRepository = true;
                         break;
                     }
-                    ++i;
                 }
             }
 
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 15befd0406a..ed2172c6057 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -1962,21 +1962,59 @@ QMap<QString,QString> GitClient::synchronousRemotesList(const QString &workingDi
     return result;
 }
 
-// function returns submodules in format path=url
-QMap<QString,QString> GitClient::synchronousSubmoduleList(const QString &workingDirectory)
+SubmoduleDataMap GitClient::submoduleList(const QString &workingDirectory)
 {
-    QMap<QString,QString> result;
-    if (!QFile::exists(workingDirectory + QLatin1String("/.gitmodules")))
+    SubmoduleDataMap result;
+    QString gitmodulesFileName = workingDirectory + QLatin1String("/.gitmodules");
+    if (!QFile::exists(gitmodulesFileName))
         return result;
 
-    QSettings gitmodulesFile(workingDirectory + QLatin1String("/.gitmodules"), QSettings::IniFormat);
+    static QMap<QString, SubmoduleDataMap> cachedSubmoduleData;
+
+    if (cachedSubmoduleData.contains(workingDirectory))
+        return cachedSubmoduleData.value(workingDirectory);
+    QStringList args(QLatin1String("-l"));
+
+    QStringList allConfigs = readConfig(workingDirectory, args).split(QLatin1Char('\n'));
+    const QString submoduleLineStart = QLatin1String("submodule.");
+    foreach (const QString &configLine, allConfigs) {
+        if (!configLine.startsWith(submoduleLineStart))
+            continue;
+
+        int nameStart = submoduleLineStart.size();
+        int nameEnd   = configLine.indexOf(QLatin1Char('.'), nameStart);
+
+        QString submoduleName = configLine.mid(nameStart, nameEnd - nameStart);
+
+        SubmoduleData submoduleData;
+        if (result.contains(submoduleName))
+            submoduleData = result[submoduleName];
 
-    foreach (const QString &submoduleGroup, gitmodulesFile.childGroups()) {
-        gitmodulesFile.beginGroup(submoduleGroup);
-        result.insertMulti(gitmodulesFile.value(QLatin1String("path")).toString(),
-                           gitmodulesFile.value(QLatin1String("url")).toString());
-        gitmodulesFile.endGroup();
+        if (configLine.mid(nameEnd, 5) == QLatin1String(".url="))
+            submoduleData.url = configLine.mid(nameEnd + 5);
+        else if (configLine.mid(nameEnd, 8) == QLatin1String(".ignore="))
+            submoduleData.ignore = configLine.mid(nameEnd + 8);
+        else
+            continue;
+
+        result.insert(submoduleName, submoduleData);
+    }
+
+    // if config found submodules
+    if (!result.isEmpty()) {
+        QSettings gitmodulesFile(gitmodulesFileName, QSettings::IniFormat);
+
+        foreach (const QString &submoduleName, result.keys()) {
+            gitmodulesFile.beginGroup(QLatin1String("submodule \"") +
+                                      submoduleName + QLatin1Char('"'));
+            result[submoduleName].dir = gitmodulesFile.value(QLatin1String("path")).toString();
+            QString ignore = gitmodulesFile.value(QLatin1String("ignore")).toString();
+            if (!ignore.isEmpty() && result[submoduleName].ignore.isEmpty())
+                result[submoduleName].ignore = ignore;
+            gitmodulesFile.endGroup();
+        }
     }
+    cachedSubmoduleData.insert(workingDirectory, result);
 
     return result;
 }
@@ -2172,7 +2210,7 @@ void GitClient::submoduleUpdate(const QString &workingDirectory)
 
 void GitClient::promptSubmoduleUpdate(const QString &workingDirectory)
 {
-    if (!QFile::exists(workingDirectory + QLatin1String("/.gitmodules")))
+    if (submoduleList(workingDirectory).isEmpty())
         return;
 
     if (QMessageBox::question(Core::ICore::mainWindow(), tr("Submodules Found"),
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index d71b47ac888..414efe65216 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -86,6 +86,16 @@ enum StashFlag {
     NoPrompt       = 0x02
 };
 
+class SubmoduleData
+{
+public:
+    QString dir;
+    QString url;
+    QString ignore;
+};
+
+typedef QMap<QString, SubmoduleData> SubmoduleDataMap;
+
 class GitClient : public QObject
 {
     Q_OBJECT
@@ -200,7 +210,7 @@ public:
 
     QMap<QString,QString> synchronousRemotesList(const QString &workingDirectory,
                                                  QString *errorMessage = 0);
-    QMap<QString,QString> synchronousSubmoduleList(const QString &workingDirectory);
+    SubmoduleDataMap submoduleList(const QString &workingDirectory);
     bool synchronousShow(const QString &workingDirectory, const QString &id,
                               QString *output, QString *errorMessage);
 
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 55dcce53648..1eb1ec4215f 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -1323,8 +1323,9 @@ void GitPlugin::updateActions(VcsBase::VcsBasePlugin::ActionState as)
 
     foreach (QAction *repositoryAction, m_repositoryActions)
         repositoryAction->setEnabled(repositoryEnabled);
+
     m_submoduleUpdateAction->setVisible(repositoryEnabled
-            && QFile::exists(currentState().topLevel() + QLatin1String("/.gitmodules")));
+            && !m_gitClient->submoduleList(currentState().topLevel()).isEmpty());
 
     updateContinueAndAbortCommands();
     updateRepositoryBrowserAction();
-- 
GitLab