diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp index 43ed665524f..924a9ad56ea 100644 --- a/src/libs/utils/devicefileaccess.cpp +++ b/src/libs/utils/devicefileaccess.cpp @@ -250,12 +250,14 @@ QByteArray DeviceFileAccess::fileId(const FilePath &filePath) const return {}; } -bool DeviceFileAccess::refersToExecutableFile( +std::optional DeviceFileAccess::refersToExecutableFile( const FilePath &filePath, FilePath::MatchScope matchScope) const { Q_UNUSED(matchScope) - return isExecutableFile(filePath); + if (isExecutableFile(filePath)) + return filePath; + return {}; } void DeviceFileAccess::asyncFileContents( @@ -301,38 +303,42 @@ bool DesktopDeviceFileAccess::isExecutableFile(const FilePath &filePath) const return fi.isExecutable() && !fi.isDir(); } -static bool isWindowsExecutableHelper(const FilePath &filePath, const QStringView suffix) +static std::optional isWindowsExecutableHelper + (const FilePath &filePath, const QStringView suffix) { const QFileInfo fi(filePath.path().append(suffix)); - return fi.isExecutable() && !fi.isDir(); + if (!fi.isExecutable() || fi.isDir()) + return {}; + + return filePath.withNewPath(FileUtils::normalizedPathName(fi.filePath())); } -bool DesktopDeviceFileAccess::refersToExecutableFile( +std::optional DesktopDeviceFileAccess::refersToExecutableFile( const FilePath &filePath, FilePath::MatchScope matchScope) const { if (isExecutableFile(filePath)) - return true; + return filePath; if (HostOsInfo::isWindowsHost()) { if (matchScope == FilePath::WithExeSuffix || matchScope == FilePath::WithExeOrBatSuffix) { - if (isWindowsExecutableHelper(filePath, u".exe")) - return true; + if (auto res = isWindowsExecutableHelper(filePath, u".exe")) + return res; } if (matchScope == FilePath::WithBatSuffix || matchScope == FilePath::WithExeOrBatSuffix) { - if (isWindowsExecutableHelper(filePath, u".bat")) - return true; + if (auto res = isWindowsExecutableHelper(filePath, u".bat")) + return res; } if (matchScope == FilePath::WithAnySuffix) { // That's usually .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH, - static const QStringList exts = qtcEnvironmentVariable("PATHEXT").split(';'); + static const QStringList exts = qtcEnvironmentVariable("PATHEXT").toLower().split(';'); for (const QString &ext : exts) { - if (isWindowsExecutableHelper(filePath, ext)) - return true; + if (auto res = isWindowsExecutableHelper(filePath, ext)) + return res; } } } - return false; + return {}; } bool DesktopDeviceFileAccess::isReadableFile(const FilePath &filePath) const diff --git a/src/libs/utils/devicefileaccess.h b/src/libs/utils/devicefileaccess.h index 8e5633aa34a..91390c4d53b 100644 --- a/src/libs/utils/devicefileaccess.h +++ b/src/libs/utils/devicefileaccess.h @@ -47,7 +47,7 @@ protected: virtual qint64 bytesAvailable(const FilePath &filePath) const; virtual QByteArray fileId(const FilePath &filePath) const; - virtual bool refersToExecutableFile( + virtual std::optional refersToExecutableFile( const FilePath &filePath, FilePath::MatchScope matchScope) const; @@ -118,7 +118,7 @@ protected: qint64 bytesAvailable(const FilePath &filePath) const override; QByteArray fileId(const FilePath &filePath) const override; - bool refersToExecutableFile( + std::optional refersToExecutableFile( const FilePath &filePath, FilePath::MatchScope matchScope) const override; diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index b6cef68bdee..6df30ffd825 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -419,7 +419,7 @@ bool FilePath::isExecutableFile() const /// /// This is equivalent to \c isExecutableFile() in general. /// On Windows, it will check appending various suffixes, too. -bool FilePath::refersToExecutableFile(MatchScope matchScope) const +std::optional FilePath::refersToExecutableFile(MatchScope matchScope) const { return fileAccess()->refersToExecutableFile(*this, matchScope); } diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h index 2e0f45b29d7..c91403b5f74 100644 --- a/src/libs/utils/filepath.h +++ b/src/libs/utils/filepath.h @@ -184,7 +184,7 @@ public: enum MatchScope { ExactMatchOnly, WithExeSuffix, WithBatSuffix, WithExeOrBatSuffix, WithAnySuffix }; - bool refersToExecutableFile(MatchScope considerScript) const; + std::optional refersToExecutableFile(MatchScope considerScript) const; // makes sure that capitalization of directories is canonical // on Windows and macOS. This is rarely needed. diff --git a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp index a92454e169c..ea3e78dcec3 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp @@ -70,8 +70,8 @@ static std::vector> autoDetectCMakeTools() if (base.isEmpty()) continue; const FilePath suspect = base / "cmake"; - if (suspect.refersToExecutableFile(FilePath::WithAnySuffix)) - suspects << suspect; + if (std::optional foundExe = suspect.refersToExecutableFile(FilePath::WithAnySuffix)) + suspects << *foundExe; } std::vector> found;