Utils: Add a FilePath::searchAllInDirectories

A variation that does not stop on the first found item.
Useful for auto-detection scenarios.

Use "WithAnySuffix" as default to cover .cmd and .bat etc.

Change-Id: I48f36eff06699c046e34c8e2646546bcff20ae8b
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
hjk
2023-05-23 09:14:23 +02:00
parent 27a63b0930
commit ae26fa0dd7
2 changed files with 75 additions and 10 deletions

View File

@@ -1538,25 +1538,83 @@ FilePath FilePath::searchInDirectories(const FilePaths &dirs,
return {};
}
FilePath FilePath::searchInPath(const FilePaths &additionalDirs,
PathAmending amending,
const FilePathPredicate &filter,
const MatchScope &matchScope) const
FilePaths FilePath::searchAllInDirectories(const FilePaths &dirs,
const FilePathPredicate &filter,
const MatchScope &matchScope) const
{
if (isAbsolutePath())
return *this;
if (isEmpty())
return {};
FilePaths directories = devicePathEnvironmentVariable();
const FilePaths execs = appendExeExtensions(*this, matchScope);
FilePaths result;
if (isAbsolutePath()) {
for (const FilePath &filePath : execs) {
if (filePath.isExecutableFile() && (!filter || filter(filePath)))
result.append(filePath);
}
return result;
}
QSet<FilePath> alreadyCheckedDirectories;
for (const FilePath &dir : dirs) {
// Compare the initial size of the set with the size after insertion to check
// if the directory was already checked.
const int initialCount = alreadyCheckedDirectories.count();
alreadyCheckedDirectories.insert(dir);
const bool wasAlreadyChecked = alreadyCheckedDirectories.count() == initialCount;
if (dir.isEmpty() || wasAlreadyChecked)
continue;
for (const FilePath &exe : execs) {
const FilePath filePath = dir / exe.path();
if (filePath.isExecutableFile() && (!filter || filter(filePath)))
result.append(filePath);
}
}
return result;
}
static FilePaths dirsFromPath(const FilePath &anchor,
const FilePaths &additionalDirs,
FilePath::PathAmending amending)
{
FilePaths directories = anchor.devicePathEnvironmentVariable();
if (!additionalDirs.isEmpty()) {
if (amending == AppendToPath)
if (amending == FilePath::AppendToPath)
directories.append(additionalDirs);
else
directories = additionalDirs + directories;
}
return directories;
}
FilePath FilePath::searchInPath(const FilePaths &additionalDirs,
PathAmending amending,
const FilePathPredicate &filter,
MatchScope matchScope) const
{
if (isAbsolutePath())
return *this;
const FilePaths directories = dirsFromPath(*this, additionalDirs, amending);
return searchInDirectories(directories, filter, matchScope);
}
FilePaths FilePath::searchAllInPath(const FilePaths &additionalDirs,
PathAmending amending,
const FilePathPredicate &filter,
MatchScope matchScope) const
{
const FilePaths directories = dirsFromPath(*this, additionalDirs, amending);
return searchAllInDirectories(directories, filter, matchScope);
}
Environment FilePath::deviceEnvironment() const
{
if (needsDevice()) {

View File

@@ -187,11 +187,18 @@ public:
[[nodiscard]] FilePath searchInDirectories(const FilePaths &dirs,
const FilePathPredicate &filter = {},
const MatchScope &matchScope = {}) const;
const MatchScope &matchScope = WithAnySuffix) const;
[[nodiscard]] FilePaths searchAllInDirectories(const FilePaths &dirs,
const FilePathPredicate &filter = {},
const MatchScope &matchScope = WithAnySuffix) const;
[[nodiscard]] FilePath searchInPath(const FilePaths &additionalDirs = {},
PathAmending = AppendToPath,
const FilePathPredicate &filter = {},
const MatchScope &matchScope = {}) const;
MatchScope matchScope = WithAnySuffix) const;
[[nodiscard]] FilePaths searchAllInPath(const FilePaths &additionalDirs = {},
PathAmending = AppendToPath,
const FilePathPredicate &filter = {},
MatchScope matchScope = WithAnySuffix) const;
std::optional<FilePath> refersToExecutableFile(MatchScope considerScript) const;