From 465bf149d5c1dbb142ffd81bcab234716192cdee Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Tue, 17 Mar 2009 12:36:55 +0100
Subject: [PATCH] Fixes: Using a git configuration with colored output breaks
 much of the git plugin.

Task:     248067
Details:  Use --no-color where appropriate. Use a hack to remove color sequences from output for "status" since it does not support the option as of git 1.6.2.
---
 src/plugins/git/branchmodel.cpp |  3 ++-
 src/plugins/git/gitclient.cpp   | 38 ++++++++++++++++++++-------------
 src/plugins/git/gitclient.h     |  2 ++
 src/plugins/git/gitcommand.cpp  | 27 +++++++++++++++++++++++
 src/plugins/git/gitcommand.h    |  4 ++++
 5 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp
index 9c778555d9d..23c597b204e 100644
--- a/src/plugins/git/branchmodel.cpp
+++ b/src/plugins/git/branchmodel.cpp
@@ -109,7 +109,8 @@ bool RemoteBranchModel::refreshBranches(const QString &workingDirectory, bool re
                                         int *currentBranch, QString *errorMessage)
 {
     // Run branch command with verbose.
-    QStringList branchArgs(QLatin1String("-v"));
+    QStringList branchArgs;
+    branchArgs << QLatin1String(GitClient::noColorOption) << QLatin1String("-v");
     QString output;
     *currentBranch = -1;
     if (remoteBranches)
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 25a134bd46a..8baabe03a2a 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -57,8 +57,8 @@
 using namespace Git;
 using namespace Git::Internal;
 
-const char *const kGitDirectoryC = ".git";
-const char *const kBranchIndicatorC = "# On branch";
+static const char *const kGitDirectoryC = ".git";
+static const char *const kBranchIndicatorC = "# On branch";
 
 static inline QString msgServerFailure()
 {
@@ -108,6 +108,8 @@ GitClient::~GitClient()
 {
 }
 
+const char *GitClient::noColorOption = "--no-color";
+
 QString GitClient::findRepositoryForFile(const QString &fileName)
 {
     const QString gitDirectory = QLatin1String(kGitDirectoryC);
@@ -201,22 +203,24 @@ void GitClient::diff(const QString &workingDirectory,
     // when using the submit dialog.
     GitCommand *command = createCommand(workingDirectory, editor);
     // Directory diff?
+    QStringList commonDiffArgs;
+    commonDiffArgs << QLatin1String("diff") << QLatin1String(noColorOption);
     if (unstagedFileNames.empty() && stagedFileNames.empty()) {
-       QStringList arguments;
-       arguments << QLatin1String("diff") << diffArgs;
+       QStringList arguments(commonDiffArgs);
+       arguments << diffArgs;
        m_plugin->outputWindow()->append(formatCommand(binary, arguments));
        command->addJob(arguments, m_settings.timeout);
     } else {
         // Files diff.
         if (!unstagedFileNames.empty()) {
-           QStringList arguments;
-           arguments << QLatin1String("diff") << diffArgs << QLatin1String("--") << unstagedFileNames;
+           QStringList arguments(commonDiffArgs);
+           arguments << QLatin1String("--") << unstagedFileNames;
            m_plugin->outputWindow()->append(formatCommand(binary, arguments));
            command->addJob(arguments, m_settings.timeout);
         }
         if (!stagedFileNames.empty()) {
-           QStringList arguments;
-           arguments << QLatin1String("diff") << QLatin1String("--cached") << diffArgs << QLatin1String("--") << stagedFileNames;
+           QStringList arguments(commonDiffArgs);
+           arguments << QLatin1String("--cached") << diffArgs << QLatin1String("--") << stagedFileNames;
            m_plugin->outputWindow()->append(formatCommand(binary, arguments));
            command->addJob(arguments, m_settings.timeout);
         }
@@ -233,7 +237,7 @@ void GitClient::diff(const QString &workingDirectory,
     QStringList arguments;
     arguments << QLatin1String("diff");
     if (!fileName.isEmpty())
-        arguments << diffArgs << QLatin1String("--") << fileName;
+        arguments << diffArgs << QLatin1String(noColorOption) << QLatin1String("--") << fileName;
 
     const QString kind = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_KIND);
     const QString title = tr("Git Diff %1").arg(fileName);
@@ -245,6 +249,7 @@ void GitClient::diff(const QString &workingDirectory,
 
 void GitClient::status(const QString &workingDirectory)
 {
+    // @TODO: Use "--no-color" once it is supported
     QStringList statusArgs(QLatin1String("status"));
     statusArgs << QLatin1String("-u");
     executeGit(workingDirectory, statusArgs, 0, true);
@@ -255,7 +260,8 @@ void GitClient::log(const QString &workingDirectory, const QString &fileName)
     if (Git::Constants::debug)
         qDebug() << "log" << workingDirectory << fileName;
 
-    QStringList arguments(QLatin1String("log"));
+    QStringList arguments;
+    arguments << QLatin1String("log") << QLatin1String(noColorOption);
 
     if (m_settings.logCount > 0)
          arguments << QLatin1String("-n") << QString::number(m_settings.logCount);
@@ -274,8 +280,8 @@ void GitClient::show(const QString &source, const QString &id)
 {
     if (Git::Constants::debug)
         qDebug() << "show" << source << id;
-    QStringList arguments(QLatin1String("show"));
-    arguments << id;
+    QStringList arguments;
+    arguments << QLatin1String("show") << QLatin1String(noColorOption) << id;
 
     const QString title =  tr("Git Show %1").arg(id);
     const QString kind = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_KIND);
@@ -450,7 +456,7 @@ bool GitClient::synchronousShow(const QString &workingDirectory, const QString &
     if (Git::Constants::debug)
         qDebug() << Q_FUNC_INFO << workingDirectory << id;
     QStringList args(QLatin1String("show"));
-    args << id;
+    args << QLatin1String(noColorOption) << id;
     QByteArray outputText;
     QByteArray errorText;
     const bool rc = synchronousGit(workingDirectory, args, &outputText, &errorText);
@@ -633,10 +639,12 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory,
     // Run 'status'. Note that git returns exitcode 1 if there are no added files.
     QByteArray outputText;
     QByteArray errorText;
+    // @TODO: Use "--no-color" once it is supported
     QStringList statusArgs(QLatin1String("status"));
     if (untracked)
         statusArgs << QLatin1String("-u");
     const bool statusRc = synchronousGit(workingDirectory, statusArgs, &outputText, &errorText);
+    GitCommand::removeColorCodes(&outputText);
     if (output)
         *output = QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r'));
     // Is it something really fatal?
@@ -958,14 +966,14 @@ void GitClient::stashPop(const QString &workingDirectory)
 void GitClient::branchList(const QString &workingDirectory)
 {
     QStringList arguments(QLatin1String("branch"));
-    arguments << QLatin1String("-r");
+    arguments << QLatin1String("-r") << QLatin1String(noColorOption);
     executeGit(workingDirectory, arguments, 0, true);
 }
 
 void GitClient::stashList(const QString &workingDirectory)
 {
     QStringList arguments(QLatin1String("stash"));
-    arguments << QLatin1String("list");
+    arguments << QLatin1String("list") << QLatin1String(noColorOption);
     executeGit(workingDirectory, arguments, 0, true);
 }
 
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 5a9d96e7b98..046e08bc239 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -135,6 +135,8 @@ public:
 
     static QString msgNoChangedFiles();
 
+    static const char *noColorOption;
+
 public slots:
     void show(const QString &source, const QString &id);
 
diff --git a/src/plugins/git/gitcommand.cpp b/src/plugins/git/gitcommand.cpp
index dd1c3882b04..47d792d53af 100644
--- a/src/plugins/git/gitcommand.cpp
+++ b/src/plugins/git/gitcommand.cpp
@@ -121,6 +121,10 @@ void GitCommand::run()
     // Special hack: Always produce output for diff
     if (ok && output.isEmpty() && m_jobs.front().arguments.at(0) == QLatin1String("diff")) {
         output += "The file does not differ from HEAD";
+    } else {
+        // @TODO: Remove, see below
+        if (ok && m_jobs.front().arguments.at(0) == QLatin1String("status"))
+            removeColorCodes(&output);
     }
 
     if (ok && !output.isEmpty())
@@ -133,5 +137,28 @@ void GitCommand::run()
     this->deleteLater();
 }
 
+// Clean output from carriage return and ANSI color codes.
+// @TODO: Remove once all relevant commands support "--no-color",
+//("status" is  missing it as of git 1.6.2)
+
+void GitCommand::removeColorCodes(QByteArray *data)
+{
+    // Remove ansi color codes that look like "ESC[<stuff>m"
+    const QByteArray ansiColorEscape("\033[");
+    int escapePos = 0;
+    while (true) {
+        const int nextEscapePos = data->indexOf(ansiColorEscape, escapePos);
+        if (nextEscapePos == -1)
+            break;
+        const int endEscapePos = data->indexOf('m', nextEscapePos + ansiColorEscape.size());
+        if (endEscapePos != -1) {
+            data->remove(nextEscapePos, endEscapePos - nextEscapePos + 1);
+            escapePos = nextEscapePos;
+        } else {
+            escapePos = nextEscapePos + ansiColorEscape.size();
+        }
+    }
+}
+
 } // namespace Internal
 } // namespace Git
diff --git a/src/plugins/git/gitcommand.h b/src/plugins/git/gitcommand.h
index 8f32bd6862b..f4bdb34768a 100644
--- a/src/plugins/git/gitcommand.h
+++ b/src/plugins/git/gitcommand.h
@@ -50,6 +50,10 @@ public:
     void addJob(const QStringList &arguments, int timeout);
     void execute();
 
+    // Clean output from carriage return and ANSI color codes.
+    // Workaround until all relevant commands support "--no-color".
+    static void removeColorCodes(QByteArray *data);
+
 private:
     void run();
 
-- 
GitLab