Utils: Improve FileUtils::commonPath

Make it a worthy FilePath-based counterpart of Utils::commonPath.
With tests.

Change-Id: I68bae129c5d9d9dd3e46dfa6093e229f8ca0aee1
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
Alessandro Portale
2022-07-21 18:23:27 +02:00
parent 04669dfadf
commit ce7a761075
3 changed files with 89 additions and 0 deletions

View File

@@ -385,6 +385,52 @@ static QByteArray fileIdWin(HANDLE fHandle)
} }
#endif #endif
FilePath FileUtils::commonPath(const FilePaths &paths)
{
if (paths.isEmpty())
return {};
if (paths.count() == 1)
return paths.constFirst();
const FilePath &first = paths.constFirst();
const FilePaths others = paths.mid(1);
FilePath result;
// Common scheme
const QString &commonScheme = first.scheme();
auto sameScheme = [&commonScheme] (const FilePath &fp) {
return commonScheme == fp.scheme();
};
if (!allOf(others, sameScheme))
return result;
result.setScheme(commonScheme);
// Common host
const QString &commonHost = first.host();
auto sameHost = [&commonHost] (const FilePath &fp) {
return commonHost == fp.host();
};
if (!allOf(others, sameHost))
return result;
result.setHost(commonHost);
// Common path
QString commonPath;
auto sameBasePath = [&commonPath] (const FilePath &fp) {
return QString(fp.path() + '/').startsWith(commonPath);
};
const QStringList pathSegments = first.path().split('/');
for (const QString &segment : pathSegments) {
commonPath += segment + '/';
if (!allOf(others, sameBasePath))
return result;
result.setPath(commonPath.chopped(1));
}
return result;
}
QByteArray FileUtils::fileId(const FilePath &fileName) QByteArray FileUtils::fileId(const FilePath &fileName)
{ {
QByteArray result; QByteArray result;

View File

@@ -134,6 +134,7 @@ public:
static bool isRelativePath(const QString &fileName); static bool isRelativePath(const QString &fileName);
static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); } static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
static FilePath commonPath(const FilePath &oldCommonPath, const FilePath &fileName); static FilePath commonPath(const FilePath &oldCommonPath, const FilePath &fileName);
static FilePath commonPath(const FilePaths &paths);
static QByteArray fileId(const FilePath &fileName); static QByteArray fileId(const FilePath &fileName);
static FilePath homePath(); static FilePath homePath();

View File

@@ -66,6 +66,8 @@ private slots:
void linkFromString(); void linkFromString();
void pathAppended_data(); void pathAppended_data();
void pathAppended(); void pathAppended();
void commonPath_data();
void commonPath();
void asyncLocalCopy(); void asyncLocalCopy();
@@ -590,6 +592,46 @@ void tst_fileutils::pathAppended_data()
QTest::newRow("u4") << "a/b" << "c/d" << "a/b/c/d"; QTest::newRow("u4") << "a/b" << "c/d" << "a/b/c/d";
} }
void tst_fileutils::commonPath()
{
QFETCH(FilePaths, list);
QFETCH(FilePath, expected);
const FilePath result = FileUtils::commonPath(list);
QCOMPARE(expected.toString(), result.toString());
}
void tst_fileutils::commonPath_data()
{
QTest::addColumn<FilePaths>("list");
QTest::addColumn<FilePath>("expected");
const FilePath p1 = FilePath::fromString("c:/Program Files(x86)");
const FilePath p2 = FilePath::fromString("c:/Program Files(x86)/Ide");
const FilePath p3 = FilePath::fromString("c:/Program Files(x86)/Ide/Qt Creator");
const FilePath p4 = FilePath::fromString("c:/Program Files");
const FilePath p5 = FilePath::fromString("c:");
const FilePath url1 = FilePath::fromString("http://127.0.0.1/./");
const FilePath url2 = FilePath::fromString("https://127.0.0.1/./");
const FilePath url3 = FilePath::fromString("http://www.qt.io/./");
const FilePath url4 = FilePath::fromString("https://www.qt.io/./");
const FilePath url5 = FilePath::fromString("https://www.qt.io/ide/");
const FilePath url6 = FilePath::fromString("http:///./");
QTest::newRow("Zero paths") << FilePaths{} << FilePath();
QTest::newRow("Single path") << FilePaths{ p1 } << p1;
QTest::newRow("3 identical paths") << FilePaths{ p1, p1, p1 } << p1;
QTest::newRow("3 paths, common path") << FilePaths{ p1, p2, p3 } << p1;
QTest::newRow("3 paths, no common path") << FilePaths{ p1, p2, p4 } << p5;
QTest::newRow("3 paths, first is part of second") << FilePaths{ p4, p1, p3 } << p5;
QTest::newRow("Common scheme") << FilePaths{ url1, url3 } << url6;
QTest::newRow("Different scheme") << FilePaths{ url1, url2 } << FilePath();
QTest::newRow("Common host") << FilePaths{ url4, url5 } << url4;
QTest::newRow("Different host") << FilePaths{ url1, url3 } << url6;
}
void tst_fileutils::asyncLocalCopy() void tst_fileutils::asyncLocalCopy()
{ {
const FilePath orig = FilePath::fromString(rootPath).pathAppended("x/y/fileToCopy.txt"); const FilePath orig = FilePath::fromString(rootPath).pathAppended("x/y/fileToCopy.txt");