From d02d67d58c5fc8ade5a09deb31dee042275ba6bf Mon Sep 17 00:00:00 2001
From: Daniel Teske <daniel.teske@nokia.com>
Date: Tue, 11 Sep 2012 13:56:08 +0200
Subject: [PATCH] Fix searchInPath in various ways

Search in path order not in extension order. That is prefer exec.bat to
exec.exe if exec.bat is earlier in the path.

On Windows only append extensions if the executable has none. (That's
how the shell works.)

Change-Id: I4774f47e5d8e71efccbce49f3facc360eb2a193e
Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com>
---
 src/libs/utils/environment.cpp | 87 +++++++++++++++++-----------------
 src/libs/utils/environment.h   |  3 +-
 2 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index 97650cb2bbd..f639970b189 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -228,59 +228,60 @@ void Environment::clear()
     m_values.clear();
 }
 
+QString Environment::searchInDirectory(const QStringList &execs, QString directory) const
+{
+    const QChar slash = QLatin1Char('/');
+    if (directory.isEmpty())
+        return QString();
+    // Avoid turing / into // on windows which triggers windows to check
+    // for network drives!
+    if (!directory.endsWith(slash))
+        directory += slash;
+
+    foreach (const QString &exec, execs) {
+        QFileInfo fi(directory + exec);
+        if (fi.exists() && fi.isFile() && fi.isExecutable())
+            return fi.absoluteFilePath();
+    }
+    return QString();
+}
+
 QString Environment::searchInPath(const QString &executable,
                                   const QStringList &additionalDirs) const
 {
+    QString exec = QDir::cleanPath(expandVariables(executable));
+    QFileInfo fi(exec);
+    if (fi.isAbsolute())
+        return exec;
+
+    if (executable.isEmpty())
+        return QString();
+
     QStringList execs;
-    execs << executable;
 #ifdef Q_OS_WIN
     // Check all the executable extensions on windows:
-    QStringList extensions = value(QLatin1String("PATHEXT")).split(QLatin1Char(';'));
+    // PATHEXT is only used if the executable has no extension
+    if (fi.suffix().isEmpty()) {
+        QStringList extensions = value(QLatin1String("PATHEXT")).split(QLatin1Char(';'));
 
-    // .exe.bat is legal (and run when starting new.exe), so always go through the complete list once:
-    foreach (const QString &ext, extensions)
-        execs << executable + ext.toLower();
+        foreach (const QString &ext, extensions)
+            execs << executable + ext.toLower();
+    }
 #endif
-    return searchInPath(execs, additionalDirs);
-}
 
-QString Environment::searchInPath(const QStringList &executables,
-                                  const QStringList &additionalDirs) const
-{
-    const QChar slash = QLatin1Char('/');
-    foreach (const QString &executable, executables) {
-        QString exec = QDir::cleanPath(expandVariables(executable));
-
-        if (exec.isEmpty())
-            continue;
-
-        QFileInfo baseFi(exec);
-        if (baseFi.isAbsolute() && baseFi.exists())
-            return exec;
-
-        // Check in directories:
-        foreach (const QString &dir, additionalDirs) {
-            if (dir.isEmpty())
-                continue;
-            QFileInfo fi(dir + QLatin1Char('/') + exec);
-            if (fi.isFile() && fi.isExecutable())
-                return fi.absoluteFilePath();
-        }
+    foreach (QString dir, additionalDirs) {
+        QString tmp = searchInDirectory(execs, dir);
+        if (!tmp.isEmpty())
+            return tmp;
+    }
 
-        // Check in path:
-        if (exec.indexOf(slash) != -1)
-            continue;
-        foreach (const QString &p, path()) {
-            QString fp = QDir::fromNativeSeparators(p);
-            // Avoid turing / into // on windows which triggers windows to check
-            // for network drives!
-            if (!fp.endsWith(slash))
-                fp += slash;
-            fp += exec;
-            const QFileInfo fi(fp);
-            if (fi.exists() && fi.isExecutable() && !fi.isDir())
-                return fi.absoluteFilePath();
-        }
+    if (executable.indexOf(QLatin1Char('/')) != -1)
+        return QString();
+
+    foreach (const QString &p, path()) {
+        QString tmp = searchInDirectory(execs, QDir::fromNativeSeparators(p));
+        if (!tmp.isEmpty())
+            return tmp;
     }
     return QString();
 }
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index ff491c264b1..1e9e7c045d8 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -108,8 +108,7 @@ public:
     bool operator==(const Environment &other) const;
 
 private:
-    QString searchInPath(const QStringList &executables,
-                         const QStringList &additionalDirs = QStringList()) const;
+    QString searchInDirectory(const QStringList &execs, QString directory) const;
     QMap<QString, QString> m_values;
 };
 
-- 
GitLab