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 {
|
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("?"))
|
// Only absolute paths are currently supported
|
||||||
return path;
|
// 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(
|
const QString currentComponent = patternComponents.front().toString();
|
||||||
Utils::FileFilter({path.fileName()}, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot));
|
FilePath currentPath = path / currentComponent;
|
||||||
|
|
||||||
if (entries.isEmpty())
|
if (!currentComponent.contains("*") && !currentComponent.contains("?") && currentPath.exists())
|
||||||
return path;
|
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(); });
|
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()
|
Macros *McuSdkRepository::globalMacros()
|
||||||
@@ -60,7 +82,32 @@ void McuSdkRepository::expandVariablesAndWildcards()
|
|||||||
for (const auto &target : std::as_const(mcuTargets)) {
|
for (const auto &target : std::as_const(mcuTargets)) {
|
||||||
auto macroExpander = getMacroExpander(*target);
|
auto macroExpander = getMacroExpander(*target);
|
||||||
for (const auto &package : target->packages()) {
|
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()
|
void McuSupportTest::test_processWildcards_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("package_label");
|
QTest::addColumn<QString>("package_label");
|
||||||
QTest::addColumn<QString>("path");
|
QTest::addColumn<QString>("expected_path");
|
||||||
QTest::addColumn<bool>("isFile");
|
QTest::addColumn<QStringList>("paths");
|
||||||
|
|
||||||
QTest::newRow("\"*\" at the end") << "FAKE_WILDCARD_TEST_1"
|
QTest::newRow("wildcard_at_the_end") << "FAKE_WILDCARD_TEST_1" << "folder-123" << QStringList {"folder-123/" };
|
||||||
<< "folder-123" << false;
|
QTest::newRow("wildcard_in_th_middle") << "FAKE_WILDCARD_TEST_2" << "file-123.exe" << QStringList {"file-123.exe"};
|
||||||
QTest::newRow("\"*\" in the middle") << "FAKE_WILDCARD_TEST_2"
|
QTest::newRow("wildcard_at_the_end") << "FAKE_WILDCARD_TEST_3" << "123-file.exe" << QStringList( "123-file.exe");
|
||||||
<< "file-123.exe" << true;
|
QTest::newRow("multi_wildcards")
|
||||||
QTest::newRow("\"*\" at the start") << "FAKE_WILDCARD_TEST_3"
|
<< "FAKE_WILDCARD_TEST_MULTI"
|
||||||
<< "123-file.exe" << true;
|
<< "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()
|
void McuSupportTest::test_processWildcards()
|
||||||
{
|
{
|
||||||
QFETCH(QString, package_label);
|
QFETCH(QString, package_label);
|
||||||
QFETCH(QString, path);
|
QFETCH(QString, expected_path);
|
||||||
QFETCH(bool, isFile);
|
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 [targets, packages] = createTestingKitTargetsAndPackages(wildcards_test_kit);
|
||||||
auto testWildcardsPackage = findOrDefault(packages, [&](const McuPackagePtr &pkg) {
|
auto testWildcardsPackage = findOrDefault(packages, [&](const McuPackagePtr &pkg) {
|
||||||
return (pkg->label() == package_label);
|
return (pkg->label() == package_label);
|
||||||
});
|
});
|
||||||
QVERIFY(testWildcardsPackage != nullptr);
|
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()
|
void McuSupportTest::test_nonemptyVersionDetector()
|
||||||
|
|||||||
@@ -34,6 +34,13 @@ constexpr auto wildcards_test_kit = R"(
|
|||||||
"defaultValue": "%{MCU_TESTING_FOLDER}/wildcards/*-file.exe",
|
"defaultValue": "%{MCU_TESTING_FOLDER}/wildcards/*-file.exe",
|
||||||
"envVar": "",
|
"envVar": "",
|
||||||
"type": "path"
|
"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