Utils: Combine some of the iterateWithFind overloads

Change-Id: I668447d0049f2e35cd0c76d2c5708779196167ec
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
hjk
2022-10-11 13:58:26 +02:00
parent 48755cf7fd
commit b1471fe61f
14 changed files with 83 additions and 169 deletions

View File

@@ -521,26 +521,15 @@ void FilePath::iterateDirectory(const IterateDirCallback &callBack, const FileFi
return; return;
} }
QDirIterator it(path(), filter.nameFilters, filter.fileFilters, filter.iteratorFlags);
while (it.hasNext()) {
if (!callBack(FilePath::fromString(it.next())))
return;
}
}
void FilePath::iterateDirectory(const IterateDirWithInfoCallback &callBack,
const FileFilter &filter) const
{
if (needsDevice()) {
QTC_ASSERT(s_deviceHooks.iterateDirectoryWithInfo, return);
s_deviceHooks.iterateDirectoryWithInfo(*this, callBack, filter);
return;
}
QDirIterator it(path(), filter.nameFilters, filter.fileFilters, filter.iteratorFlags); QDirIterator it(path(), filter.nameFilters, filter.fileFilters, filter.iteratorFlags);
while (it.hasNext()) { while (it.hasNext()) {
const FilePath path = FilePath::fromString(it.next()); const FilePath path = FilePath::fromString(it.next());
if (!callBack(path, path.filePathInfo())) bool res = false;
if (callBack.index() == 0)
res = std::get<0>(callBack)(path);
else
res = std::get<1>(callBack)(path, path.filePathInfo());
if (!res)
return; return;
} }
} }

View File

@@ -154,17 +154,20 @@ public:
[[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const; [[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const;
[[nodiscard]] FilePath withNewPath(const QString &newPath) const; [[nodiscard]] FilePath withNewPath(const QString &newPath) const;
using IterateDirCallback = std::function<bool(const FilePath &item)>; using IterateDirCallback
using IterateDirWithInfoCallback = std::variant<
= std::function<bool(const FilePath &item, const FilePathInfo &info)>; std::function<bool(const FilePath &item)>,
std::function<bool(const FilePath &item, const FilePathInfo &info)>
>;
void iterateDirectory(const IterateDirCallback &callBack, const FileFilter &filter) const; void iterateDirectory(
void iterateDirectory(const IterateDirWithInfoCallback &callBack, const IterateDirCallback &callBack,
const FileFilter &filter) const; const FileFilter &filter) const;
static void iterateDirectories(const FilePaths &dirs, static void iterateDirectories(
const IterateDirCallback &callBack, const FilePaths &dirs,
const FileFilter &filter); const IterateDirCallback &callBack,
const FileFilter &filter);
enum PathAmending { AppendToPath, PrependToPath }; enum PathAmending { AppendToPath, PrependToPath };
[[nodiscard]] FilePath searchInPath(const FilePaths &additionalDirs = {}, [[nodiscard]] FilePath searchInPath(const FilePaths &additionalDirs = {},
@@ -270,10 +273,6 @@ public:
const FilePath::IterateDirCallback &, // Abort on 'false' return. const FilePath::IterateDirCallback &, // Abort on 'false' return.
const FileFilter &)> const FileFilter &)>
iterateDirectory; iterateDirectory;
std::function<void(const FilePath &,
const FilePath::IterateDirWithInfoCallback &, // Abort on 'false' return.
const FileFilter &)>
iterateDirectoryWithInfo;
std::function<std::optional<QByteArray>(const FilePath &, qint64, qint64)> fileContents; std::function<std::optional<QByteArray>(const FilePath &, qint64, qint64)> fileContents;
std::function<bool(const FilePath &, const QByteArray &, qint64)> writeFileContents; std::function<bool(const FilePath &, const QByteArray &, qint64)> writeFileContents;
std::function<QDateTime(const FilePath &)> lastModified; std::function<QDateTime(const FilePath &)> lastModified;

View File

@@ -587,10 +587,10 @@ FilePath FileUtils::getOpenFilePathFromDevice(QWidget *parent,
#endif // QT_WIDGETS_LIB #endif // QT_WIDGETS_LIB
// Used on 'ls' output on unix-like systems. // Used on 'ls' output on unix-like systems.
void FileUtils::iterateLsOutput(const FilePath &base, static void iterateLsOutput(const FilePath &base,
const QStringList &entries, const QStringList &entries,
const FileFilter &filter, const FileFilter &filter,
const std::function<bool (const FilePath &)> &callBack) const FilePath::IterateDirCallback &callBack)
{ {
const QList<QRegularExpression> nameRegexps = const QList<QRegularExpression> nameRegexps =
transform(filter.nameFilters, [](const QString &filter) { transform(filter.nameFilters, [](const QString &filter) {
@@ -615,7 +615,13 @@ void FileUtils::iterateLsOutput(const FilePath &base,
for (const QString &entry : entries) { for (const QString &entry : entries) {
if (!nameMatches(entry)) if (!nameMatches(entry))
continue; continue;
if (!callBack(base.pathAppended(entry))) const FilePath current = base.pathAppended(entry);
bool res = false;
if (callBack.index() == 0)
res = std::get<0>(callBack)(current);
else
res = std::get<1>(callBack)(current, current.filePathInfo());
if (!res)
break; break;
} }
} }
@@ -675,11 +681,12 @@ FilePathInfo FileUtils::filePathInfoFromTriple(const QString &infos)
return {size, flags, dt}; return {size, flags, dt};
} }
bool iterateWithFind(const FilePath &filePath, static bool iterateWithFindHelper(
const FileFilter &filter, const FilePath &filePath,
const std::function<RunResult(const CommandLine &)> &runInShell, const FileFilter &filter,
const std::function<bool(const QString &)> callBack, const std::function<RunResult(const CommandLine &)> &runInShell,
const QString &extraArguments) const std::function<bool(const QString &)> callBack,
const QString &extraArguments)
{ {
QTC_CHECK(filePath.isAbsolutePath()); QTC_CHECK(filePath.isAbsolutePath());
const QStringList arguments = filter.asFindArguments(filePath.path()); const QStringList arguments = filter.asFindArguments(filePath.path());
@@ -716,29 +723,16 @@ bool iterateWithFind(const FilePath &filePath,
} }
// returns whether 'find' could be used. // returns whether 'find' could be used.
static bool iterateWithFind(const FilePath &filePath, static bool iterateWithFind(
const FileFilter &filter, const FilePath &filePath,
const std::function<RunResult(const CommandLine &)> &runInShell, const FileFilter &filter,
const FilePath::IterateDirCallback &callBack) const std::function<RunResult(const CommandLine &)> &runInShell,
const FilePath::IterateDirCallback &callBack)
{ {
const auto toFilePath = [&filePath, &callBack](const QString &entry){ const auto toFilePath = [&filePath, &callBack](const QString &entry) {
return callBack(filePath.withNewPath(entry)); if (callBack.index() == 0)
}; return std::get<0>(callBack)(filePath.withNewPath(entry));
return iterateWithFind(filePath, filter, runInShell, toFilePath, {});
}
// returns whether 'find' could be used.
static bool iterateWithFind(const FilePath &filePath,
const FileFilter &filter,
const std::function<RunResult(const CommandLine &)> &runInShell,
const FilePath::IterateDirWithInfoCallback &callBack)
{
// TODO: Using stat -L will always return the link target, not the link itself.
// We may wan't to add the information that it is a link at some point.
const QString infoArgs(R"(-exec echo -n \"{}\"" " \; -exec stat -L -c "%f %Y %s" "{}" \;)");
const auto toFilePathAndInfo = [&filePath, &callBack](const QString &entry) {
const QString fileName = entry.mid(1, entry.lastIndexOf('\"') - 1); const QString fileName = entry.mid(1, entry.lastIndexOf('\"') - 1);
const QString infos = entry.mid(fileName.length() + 3); const QString infos = entry.mid(fileName.length() + 3);
@@ -747,10 +741,16 @@ static bool iterateWithFind(const FilePath &filePath,
return true; return true;
const FilePath fp = filePath.withNewPath(fileName); const FilePath fp = filePath.withNewPath(fileName);
return callBack(fp, fi); return std::get<1>(callBack)(fp, fi);
}; };
return iterateWithFind(filePath, filter, runInShell, toFilePathAndInfo, infoArgs); // TODO: Using stat -L will always return the link target, not the link itself.
// We may wan't to add the information that it is a link at some point.
QString infoArgs;
if (callBack.index() == 1)
infoArgs = R"(-exec echo -n \"{}\"" " \; -exec stat -L -c "%f %Y %s" "{}" \;)";
return iterateWithFindHelper(filePath, filter, runInShell, toFilePath, infoArgs);
} }
static void findUsingLs(const QString &current, static void findUsingLs(const QString &current,
@@ -777,8 +777,6 @@ void FileUtils::iterateUnixDirectory(const FilePath &filePath,
const std::function<RunResult (const CommandLine &)> &runInShell, const std::function<RunResult (const CommandLine &)> &runInShell,
const FilePath::IterateDirCallback &callBack) const FilePath::IterateDirCallback &callBack)
{ {
QTC_ASSERT(callBack, return);
// We try to use 'find' first, because that can filter better directly. // We try to use 'find' first, because that can filter better directly.
// Unfortunately, it's not installed on all devices by default. // Unfortunately, it's not installed on all devices by default.
if (useFind && *useFind) { if (useFind && *useFind) {
@@ -790,31 +788,7 @@ void FileUtils::iterateUnixDirectory(const FilePath &filePath,
// if we do not have find - use ls as fallback // if we do not have find - use ls as fallback
QStringList entries; QStringList entries;
findUsingLs(filePath.path(), filter, runInShell, &entries); findUsingLs(filePath.path(), filter, runInShell, &entries);
FileUtils::iterateLsOutput(filePath, entries, filter, callBack); iterateLsOutput(filePath, entries, filter, callBack);
}
void FileUtils::iterateUnixDirectory(const FilePath &filePath,
const FileFilter &filter,
bool *useFind,
const std::function<RunResult(const CommandLine &)> &runInShell,
const FilePath::IterateDirWithInfoCallback &callBack)
{
QTC_ASSERT(callBack, return);
// We try to use 'find' first, because that can filter better directly.
// Unfortunately, it's not installed on all devices by default.
if (useFind && *useFind) {
if (iterateWithFind(filePath, filter, runInShell, callBack))
return;
*useFind = false; // remember the failure for the next time and use the 'ls' fallback below.
}
// if we do not have find - use ls as fallback
QStringList entries;
findUsingLs(filePath.path(), filter, runInShell, &entries);
FileUtils::iterateLsOutput(filePath, entries, filter, [&callBack](const FilePath & filePath){
return callBack(filePath, filePath.filePathInfo());
});
} }
/*! /*!

View File

@@ -86,12 +86,6 @@ public:
static FilePaths toFilePathList(const QStringList &paths); static FilePaths toFilePathList(const QStringList &paths);
static void iterateLsOutput(
const FilePath &base,
const QStringList &entries,
const FileFilter &filter,
const std::function<bool(const FilePath &)> &callBack);
static void iterateUnixDirectory( static void iterateUnixDirectory(
const FilePath &base, const FilePath &base,
const FileFilter &filter, const FileFilter &filter,
@@ -99,13 +93,6 @@ public:
const std::function<RunResult(const CommandLine &)> &runInShell, const std::function<RunResult(const CommandLine &)> &runInShell,
const FilePath::IterateDirCallback &callBack); const FilePath::IterateDirCallback &callBack);
static void iterateUnixDirectory(
const FilePath &base,
const FileFilter &filter,
bool *useFind,
const std::function<RunResult(const CommandLine &)> &runInShell,
const FilePath::IterateDirWithInfoCallback &callBack);
static qint64 bytesAvailableFromDFOutput(const QByteArray &dfOutput); static qint64 bytesAvailableFromDFOutput(const QByteArray &dfOutput);
static FilePathInfo filePathInfoFromTriple(const QString &infos); static FilePathInfo filePathInfoFromTriple(const QString &infos);

View File

@@ -948,17 +948,8 @@ bool DockerDevice::ensureReachable(const FilePath &other) const
} }
void DockerDevice::iterateDirectory(const FilePath &filePath, void DockerDevice::iterateDirectory(const FilePath &filePath,
const FilePath::IterateDirCallback &callBack, const FilePath::IterateDirCallback &callBack,
const FileFilter &filter) const const FileFilter &filter) const
{
QTC_ASSERT(handlesFile(filePath), return);
auto runInShell = [this](const CommandLine &cmd) { return d->runInShell(cmd); };
FileUtils::iterateUnixDirectory(filePath, filter, &d->m_useFind, runInShell, callBack);
}
void DockerDevice::iterateDirectory(const FilePath &filePath,
const FilePath::IterateDirWithInfoCallback &callBack,
const FileFilter &filter) const
{ {
QTC_ASSERT(handlesFile(filePath), return); QTC_ASSERT(handlesFile(filePath), return);
auto runInShell = [this](const CommandLine &cmd) { return d->runInShell(cmd); }; auto runInShell = [this](const CommandLine &cmd) { return d->runInShell(cmd); };

View File

@@ -99,12 +99,10 @@ public:
bool copyFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const override; bool copyFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const override;
bool renameFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const override; bool renameFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const override;
Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const override; Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const override;
void iterateDirectory(const Utils::FilePath &filePath, void iterateDirectory(
const Utils::FilePath::IterateDirCallback &callBack, const Utils::FilePath &filePath,
const Utils::FileFilter &filter) const override; const Utils::FilePath::IterateDirCallback &callBack,
void iterateDirectory(const Utils::FilePath &filePath, const Utils::FileFilter &filter) const override;
const Utils::FilePath::IterateDirWithInfoCallback &callBack,
const Utils::FileFilter &filter) const override;
std::optional<QByteArray> fileContents(const Utils::FilePath &filePath, std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit, qint64 limit,
qint64 offset) const override; qint64 offset) const override;

View File

@@ -136,9 +136,10 @@ bool DesktopDevice::handlesFile(const FilePath &filePath) const
return !filePath.needsDevice(); return !filePath.needsDevice();
} }
void DesktopDevice::iterateDirectory(const FilePath &filePath, void DesktopDevice::iterateDirectory(
const std::function<bool(const FilePath &)> &callBack, const FilePath &filePath,
const FileFilter &filter) const const FilePath::IterateDirCallback &callBack,
const FileFilter &filter) const
{ {
QTC_CHECK(!filePath.needsDevice()); QTC_CHECK(!filePath.needsDevice());
filePath.iterateDirectory(callBack, filter); filePath.iterateDirectory(callBack, filter);

View File

@@ -50,9 +50,10 @@ public:
bool renameFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const override; bool renameFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const override;
QDateTime lastModified(const Utils::FilePath &filePath) const override; QDateTime lastModified(const Utils::FilePath &filePath) const override;
Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const override; Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const override;
void iterateDirectory(const Utils::FilePath &filePath, void iterateDirectory(
const std::function<bool(const Utils::FilePath &)> &callBack, const Utils::FilePath &filePath,
const Utils::FileFilter &filter) const override; const Utils::FilePath::IterateDirCallback &callBack,
const Utils::FileFilter &filter) const override;
std::optional<QByteArray> fileContents(const Utils::FilePath &filePath, std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit, qint64 limit,
qint64 offset) const override; qint64 offset) const override;

View File

@@ -528,14 +528,6 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
device->iterateDirectory(filePath, callBack, filter); device->iterateDirectory(filePath, callBack, filter);
}; };
deviceHooks.iterateDirectoryWithInfo = [](const FilePath &filePath,
const FilePath::IterateDirWithInfoCallback &callBack,
const FileFilter &filter) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return );
device->iterateDirectory(filePath, callBack, filter);
};
deviceHooks.fileContents = deviceHooks.fileContents =
[](const FilePath &filePath, qint64 maxSize, qint64 offset) -> std::optional<QByteArray> { [](const FilePath &filePath, qint64 maxSize, qint64 offset) -> std::optional<QByteArray> {
auto device = DeviceManager::deviceForPath(filePath); auto device = DeviceManager::deviceForPath(filePath);

View File

@@ -365,15 +365,6 @@ void IDevice::iterateDirectory(const FilePath &filePath,
QTC_CHECK(false); QTC_CHECK(false);
} }
void IDevice::iterateDirectory(const FilePath &filePath,
const FilePath::IterateDirWithInfoCallback &callBack,
const FileFilter &filter) const
{
iterateDirectory(filePath, [callBack](const FilePath &path) {
return callBack(path, path.filePathInfo());
}, filter);
}
std::optional<QByteArray> IDevice::fileContents(const FilePath &filePath, std::optional<QByteArray> IDevice::fileContents(const FilePath &filePath,
qint64 limit, qint64 limit,
qint64 offset) const qint64 offset) const

View File

@@ -237,13 +237,10 @@ public:
virtual Utils::FilePath searchExecutable(const QString &fileName, virtual Utils::FilePath searchExecutable(const QString &fileName,
const Utils::FilePaths &dirs) const; const Utils::FilePaths &dirs) const;
virtual Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const; virtual Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const;
virtual void iterateDirectory(const Utils::FilePath &filePath, virtual void iterateDirectory(
const Utils::FilePath::IterateDirCallback &callBack, const Utils::FilePath &filePath,
const Utils::FileFilter &filter) const; const Utils::FilePath::IterateDirCallback &callBack,
const Utils::FileFilter &filter) const;
virtual void iterateDirectory(const Utils::FilePath &filePath,
const Utils::FilePath::IterateDirWithInfoCallback &callBack,
const Utils::FileFilter &filter) const;
virtual std::optional<QByteArray> fileContents(const Utils::FilePath &filePath, virtual std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit, qint64 limit,

View File

@@ -1296,15 +1296,6 @@ void LinuxDevice::iterateDirectory(const FilePath &filePath,
FileUtils::iterateUnixDirectory(filePath, filter, &d->m_useFind, runInShell, callBack); FileUtils::iterateUnixDirectory(filePath, filter, &d->m_useFind, runInShell, callBack);
} }
void LinuxDevice::iterateDirectory(const FilePath &filePath,
const FilePath::IterateDirWithInfoCallback &callBack,
const FileFilter &filter) const
{
QTC_ASSERT(handlesFile(filePath), return);
auto runInShell = [this](const CommandLine &cmd) { return d->runInShell(cmd); };
FileUtils::iterateUnixDirectory(filePath, filter, &d->m_useFind, runInShell, callBack);
}
FilePathInfo LinuxDevice::filePathInfo(const FilePath &filePath) const FilePathInfo LinuxDevice::filePathInfo(const FilePath &filePath) const
{ {
QTC_ASSERT(handlesFile(filePath), return {}); QTC_ASSERT(handlesFile(filePath), return {});

View File

@@ -55,9 +55,6 @@ public:
void iterateDirectory(const Utils::FilePath &filePath, void iterateDirectory(const Utils::FilePath &filePath,
const Utils::FilePath::IterateDirCallback &callBack, const Utils::FilePath::IterateDirCallback &callBack,
const Utils::FileFilter &filter) const override; const Utils::FileFilter &filter) const override;
void iterateDirectory(const Utils::FilePath &filePath,
const Utils::FilePath::IterateDirWithInfoCallback &callBack,
const Utils::FileFilter &filter) const override;
std::optional<QByteArray> fileContents(const Utils::FilePath &filePath, std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit, qint64 limit,
qint64 offset) const override; qint64 offset) const override;

View File

@@ -117,16 +117,22 @@ void tst_fsengine::initTestCase()
return FilePath::fromString(filePath.path()).symLinkTarget(); return FilePath::fromString(filePath.path()).symLinkTarget();
}; };
deviceHooks.iterateDirectory = [](const FilePath &filePath, deviceHooks.iterateDirectory = [](const FilePath &filePath,
const std::function<bool(const FilePath &)> &callBack, const FilePath::IterateDirCallback &callBack,
const FileFilter &filter) { const FileFilter &filter) {
return FilePath::fromString(filePath.path()) const FilePath fp = FilePath::fromString(filePath.path());
.iterateDirectory( if (callBack.index() == 0) {
[&filePath, &callBack](const FilePath &path) -> bool { fp.iterateDirectory(
const FilePath devicePath = path.onDevice(filePath); [&filePath, cb = std::get<0>(callBack)](const FilePath &path) {
return cb(path.onDevice(filePath));
return callBack(devicePath);
}, },
filter); filter);
} else {
fp.iterateDirectory(
[&filePath, cb = std::get<1>(callBack)](const FilePath &path, const FilePathInfo &fpi) {
return cb(path.onDevice(filePath), fpi);
},
filter);
}
}; };
deviceHooks.asyncFileContents = [](const Continuation<const std::optional<QByteArray> &> &cont, deviceHooks.asyncFileContents = [](const Continuation<const std::optional<QByteArray> &> &cont,
const FilePath &filePath, const FilePath &filePath,