forked from qt-creator/qt-creator
McuSupport: Support expanding multiple wildcards in a path
To support defining default paths such as "Microsoft Visual Studio/2019 /*/VC/Tools/MSVC/*/bin/Hostx64/x64" Change-Id: I889439a0f2a05b15121a28fbf2b50acde2e74968 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Rainer Keller <Rainer.Keller@qt.io> Reviewed-by: Eike Ziller <eike.ziller@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
@@ -30,23 +30,45 @@ using namespace Utils;
|
||||
|
||||
namespace McuSupport::Internal {
|
||||
|
||||
static const Utils::FilePath expandWildcards(const Utils::FilePath& path)
|
||||
// Utils::FileFilter do not support globbing with "*" placed in the middle of the path,
|
||||
// since it is required for paths such as "Microsoft Visual Studio/2019/*/VC/Tools/MSVC/*/bin/Hostx64/x64"
|
||||
// The filter is applied for each time a wildcard character is found in a path component.
|
||||
// Returns a pair of the longest path if multiple ones exists and the number of components that were not found.
|
||||
static const std::pair<Utils::FilePath, int> expandWildcards(
|
||||
const FilePath path, const QList<QStringView> patternComponents)
|
||||
{
|
||||
if (!path.fileName().contains("*") && !path.fileName().contains("?"))
|
||||
return path;
|
||||
// Only absolute paths are currently supported
|
||||
// Call FilePath::cleanPath on the path before calling this function
|
||||
if (!path.exists() || path.isRelativePath())
|
||||
return {path, patternComponents.size()};
|
||||
|
||||
const FilePath p = path.parentDir();
|
||||
// All components are found
|
||||
if (patternComponents.empty())
|
||||
return {path, patternComponents.size()};
|
||||
|
||||
auto entries = p.dirEntries(
|
||||
Utils::FileFilter({path.fileName()}, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot));
|
||||
const QString currentComponent = patternComponents.front().toString();
|
||||
FilePath currentPath = path / currentComponent;
|
||||
|
||||
if (entries.isEmpty())
|
||||
return path;
|
||||
if (!currentComponent.contains("*") && !currentComponent.contains("?") && currentPath.exists())
|
||||
return expandWildcards(path / currentComponent,
|
||||
{patternComponents.constBegin() + 1, patternComponents.constEnd()});
|
||||
|
||||
auto entries = path.dirEntries(
|
||||
Utils::FileFilter({currentComponent}, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot));
|
||||
|
||||
std::pair<FilePath, int> retPair = {path, patternComponents.size()};
|
||||
|
||||
// Return the last match (can correspond to the latest version)
|
||||
sort(entries, [](const FilePath &a, const FilePath &b) { return a.fileName() < b.fileName(); });
|
||||
for (const auto &entry : entries) {
|
||||
auto [entry_path, remaining_components] = expandWildcards(entry,
|
||||
{patternComponents.constBegin()
|
||||
+ 1,
|
||||
patternComponents.constEnd()});
|
||||
if (remaining_components <= retPair.second)
|
||||
retPair = {entry_path, remaining_components};
|
||||
}
|
||||
|
||||
return entries.last();
|
||||
return retPair;
|
||||
}
|
||||
|
||||
Macros *McuSdkRepository::globalMacros()
|
||||
@@ -60,7 +82,32 @@ void McuSdkRepository::expandVariablesAndWildcards()
|
||||
for (const auto &target : std::as_const(mcuTargets)) {
|
||||
auto macroExpander = getMacroExpander(*target);
|
||||
for (const auto &package : target->packages()) {
|
||||
package->setPath(expandWildcards(macroExpander->expand(package->path())));
|
||||
// Expand variables
|
||||
const auto path = macroExpander->expand(package->path());
|
||||
|
||||
//expand wildcards
|
||||
// Ignore expanding if no wildcards are found
|
||||
if (!path.path().contains("*") && !path.path().contains("?")) {
|
||||
package->setPath(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList pathComponents = path.cleanPath().path().split("/");
|
||||
|
||||
// Path components example on linux: {"", "home", "username"}
|
||||
// Path components example on windows: {"C:", "Users", "username"}
|
||||
// 2 for empty_split_entry(linux)|root(windows) + at least one component
|
||||
if (pathComponents.size() < 2) {
|
||||
package->setPath(path);
|
||||
continue;
|
||||
}
|
||||
// drop empty_split_entry(linux)|root(windows)
|
||||
pathComponents.pop_front();
|
||||
|
||||
package->setPath(
|
||||
expandWildcards(FilePath::fromString(QDir::rootPath()),
|
||||
{pathComponents.constBegin(), pathComponents.constEnd()})
|
||||
.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1703,31 +1703,43 @@ void McuSupportTest::test_addToSystemPathFlag()
|
||||
void McuSupportTest::test_processWildcards_data()
|
||||
{
|
||||
QTest::addColumn<QString>("package_label");
|
||||
QTest::addColumn<QString>("path");
|
||||
QTest::addColumn<bool>("isFile");
|
||||
QTest::addColumn<QString>("expected_path");
|
||||
QTest::addColumn<QStringList>("paths");
|
||||
|
||||
QTest::newRow("\"*\" at the end") << "FAKE_WILDCARD_TEST_1"
|
||||
<< "folder-123" << false;
|
||||
QTest::newRow("\"*\" in the middle") << "FAKE_WILDCARD_TEST_2"
|
||||
<< "file-123.exe" << true;
|
||||
QTest::newRow("\"*\" at the start") << "FAKE_WILDCARD_TEST_3"
|
||||
<< "123-file.exe" << true;
|
||||
QTest::newRow("wildcard_at_the_end") << "FAKE_WILDCARD_TEST_1" << "folder-123" << QStringList {"folder-123/" };
|
||||
QTest::newRow("wildcard_in_th_middle") << "FAKE_WILDCARD_TEST_2" << "file-123.exe" << QStringList {"file-123.exe"};
|
||||
QTest::newRow("wildcard_at_the_end") << "FAKE_WILDCARD_TEST_3" << "123-file.exe" << QStringList( "123-file.exe");
|
||||
QTest::newRow("multi_wildcards")
|
||||
<< "FAKE_WILDCARD_TEST_MULTI"
|
||||
<< "2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64"
|
||||
<< QStringList{
|
||||
"2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/",
|
||||
"2019/Alpha/Beta/Gamma/",
|
||||
"2019/Community/VC/Tools/MSVC/",
|
||||
"2019/Community/VC/Tools/MSVC/14.29.30133/bin/",
|
||||
"2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/",
|
||||
"2019/Enterprise/VC/Tools/MSVC/",
|
||||
};
|
||||
}
|
||||
|
||||
void McuSupportTest::test_processWildcards()
|
||||
{
|
||||
QFETCH(QString, package_label);
|
||||
QFETCH(QString, path);
|
||||
QFETCH(bool, isFile);
|
||||
QFETCH(QString, expected_path);
|
||||
QFETCH(QStringList, paths);
|
||||
|
||||
QVERIFY(createFakePath(testing_output_dir / "wildcards" / path, isFile));
|
||||
for (const auto &path : paths)
|
||||
QVERIFY(createFakePath(testing_output_dir / "wildcards" / path, !path.endsWith("/")));
|
||||
|
||||
auto [targets, packages] = createTestingKitTargetsAndPackages(wildcards_test_kit);
|
||||
auto testWildcardsPackage = findOrDefault(packages, [&](const McuPackagePtr &pkg) {
|
||||
return (pkg->label() == package_label);
|
||||
});
|
||||
QVERIFY(testWildcardsPackage != nullptr);
|
||||
QCOMPARE(testWildcardsPackage->path().toString(), FilePath(testing_output_dir / "wildcards" / path).toString());
|
||||
QVERIFY(paths.size() > 0);
|
||||
// FilePaths with "/" at the end and without it evaluate to different paths.
|
||||
QCOMPARE(testWildcardsPackage->path(),
|
||||
FilePath(testing_output_dir / "wildcards" / expected_path));
|
||||
}
|
||||
|
||||
void McuSupportTest::test_nonemptyVersionDetector()
|
||||
|
||||
@@ -34,6 +34,13 @@ constexpr auto wildcards_test_kit = R"(
|
||||
"defaultValue": "%{MCU_TESTING_FOLDER}/wildcards/*-file.exe",
|
||||
"envVar": "",
|
||||
"type": "path"
|
||||
},
|
||||
{
|
||||
"label": "FAKE_WILDCARD_TEST_MULTI",
|
||||
"description": "Assert '*' is replaced by possible values",
|
||||
"defaultValue": "%{MCU_TESTING_FOLDER}/wildcards/2019/*/VC/Tools/MSVC/*/bin/Hostx64/x64",
|
||||
"envVar": "",
|
||||
"type": "path"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user