forked from qt-creator/qt-creator
Utils: Make more unix find code re-usable
Change-Id: I8fe95158ed77c8f9fb8c86a8e813b5c5de425b8a Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#include "savefile.h"
|
#include "savefile.h"
|
||||||
|
|
||||||
#include "algorithm.h"
|
#include "algorithm.h"
|
||||||
|
#include "commandline.h"
|
||||||
#include "qtcassert.h"
|
#include "qtcassert.h"
|
||||||
#include "hostosinfo.h"
|
#include "hostosinfo.h"
|
||||||
|
|
||||||
@@ -583,6 +584,8 @@ FilePath FileUtils::getOpenFilePathFromDevice(QWidget *parent,
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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,
|
void FileUtils::iterateLsOutput(const FilePath &base,
|
||||||
const QStringList &entries,
|
const QStringList &entries,
|
||||||
@@ -619,7 +622,53 @@ void FileUtils::iterateLsOutput(const FilePath &base,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // QT_WIDGETS_LIB
|
// returns whether 'find' could be used.
|
||||||
|
static bool iterateWithFind(const FilePath &filePath,
|
||||||
|
const FileFilter &filter,
|
||||||
|
const std::function<QByteArray(const CommandLine &)> &runInShell,
|
||||||
|
const std::function<bool(const Utils::FilePath &)> &callBack)
|
||||||
|
{
|
||||||
|
QTC_CHECK(filePath.isAbsolutePath());
|
||||||
|
QStringList arguments{filePath.path()};
|
||||||
|
arguments << filter.asFindArguments();
|
||||||
|
|
||||||
|
const QByteArray output = runInShell({"find", arguments});
|
||||||
|
const QString out = QString::fromUtf8(output.data(), output.size());
|
||||||
|
if (!output.isEmpty() && !out.startsWith(filePath.path())) // missing find, unknown option
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const QStringList entries = out.split("\n", Qt::SkipEmptyParts);
|
||||||
|
for (const QString &entry : entries) {
|
||||||
|
if (entry.startsWith("find: ")) {
|
||||||
|
const FilePath fp = FilePath::fromString(entry);
|
||||||
|
if (!callBack(fp.onDevice(filePath)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileUtils::iterateUnixDirectory(const FilePath &filePath,
|
||||||
|
const FileFilter &filter,
|
||||||
|
bool *useFind,
|
||||||
|
const std::function<QByteArray(const CommandLine &)> &runInShell,
|
||||||
|
const std::function<bool(const FilePath &)> &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
|
||||||
|
const QByteArray output = runInShell({"ls", {"-1", "-b", "--", filePath.path()}});
|
||||||
|
const QStringList entries = QString::fromUtf8(output).split('\n', Qt::SkipEmptyParts);
|
||||||
|
FileUtils::iterateLsOutput(filePath, entries, filter, callBack);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Copies the directory specified by \a srcFilePath recursively to \a tgtFilePath. \a tgtFilePath will contain
|
Copies the directory specified by \a srcFilePath recursively to \a tgtFilePath. \a tgtFilePath will contain
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
|
class CommandLine;
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT FileUtils
|
class QTCREATOR_UTILS_EXPORT FileUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -77,10 +79,18 @@ public:
|
|||||||
|
|
||||||
static FilePaths toFilePathList(const QStringList &paths);
|
static FilePaths toFilePathList(const QStringList &paths);
|
||||||
|
|
||||||
static void iterateLsOutput(const FilePath &base,
|
static void iterateLsOutput(
|
||||||
const QStringList &entries,
|
const FilePath &base,
|
||||||
const FileFilter &filter,
|
const QStringList &entries,
|
||||||
const std::function<bool(const FilePath &)> &callBack);
|
const FileFilter &filter,
|
||||||
|
const std::function<bool(const FilePath &)> &callBack);
|
||||||
|
|
||||||
|
static void iterateUnixDirectory(
|
||||||
|
const FilePath &base,
|
||||||
|
const FileFilter &filter,
|
||||||
|
bool *useFind,
|
||||||
|
const std::function<QByteArray(const CommandLine &)> &runInShell,
|
||||||
|
const std::function<bool(const FilePath &)> &callBack);
|
||||||
|
|
||||||
static qint64 bytesAvailableFromDFOutput(const QByteArray &dfOutput);
|
static qint64 bytesAvailableFromDFOutput(const QByteArray &dfOutput);
|
||||||
|
|
||||||
|
|||||||
@@ -143,16 +143,12 @@ public:
|
|||||||
QString repoAndTag() const { return m_data.repoAndTag(); }
|
QString repoAndTag() const { return m_data.repoAndTag(); }
|
||||||
QString dockerImageId() const { return m_data.imageId; }
|
QString dockerImageId() const { return m_data.imageId; }
|
||||||
|
|
||||||
bool useFind() const { return m_useFind; }
|
|
||||||
void setUseFind(bool useFind) { m_useFind = useFind; }
|
|
||||||
|
|
||||||
Environment environment();
|
Environment environment();
|
||||||
|
|
||||||
CommandLine withDockerExecCmd(const CommandLine &cmd, bool interactive = false);
|
CommandLine withDockerExecCmd(const CommandLine &cmd, bool interactive = false);
|
||||||
|
|
||||||
bool prepareForBuild(const Target *target);
|
bool prepareForBuild(const Target *target);
|
||||||
|
|
||||||
private:
|
|
||||||
bool createContainer();
|
bool createContainer();
|
||||||
void startContainer();
|
void startContainer();
|
||||||
void stopCurrentContainer();
|
void stopCurrentContainer();
|
||||||
@@ -895,52 +891,13 @@ bool DockerDevice::ensureReachable(const FilePath &other) const
|
|||||||
return d->ensureReachable(other.parentDir());
|
return d->ensureReachable(other.parentDir());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::iterateWithFind(const FilePath &filePath,
|
|
||||||
const std::function<bool(const Utils::FilePath &)> &callBack,
|
|
||||||
const FileFilter &filter) const
|
|
||||||
{
|
|
||||||
QTC_ASSERT(callBack, return);
|
|
||||||
QTC_CHECK(filePath.isAbsolutePath());
|
|
||||||
QStringList arguments{filePath.path()};
|
|
||||||
arguments << filter.asFindArguments();
|
|
||||||
|
|
||||||
const QByteArray output = d->outputForRunInShell({"find", arguments});
|
|
||||||
const QString out = QString::fromUtf8(output.data(), output.size());
|
|
||||||
if (!output.isEmpty() && !out.startsWith(filePath.path())) { // missing find, unknown option
|
|
||||||
qCDebug(dockerDeviceLog) << "Setting 'do not use find'" << out.left(out.indexOf('\n'));
|
|
||||||
d->setUseFind(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QStringList entries = out.split("\n", Qt::SkipEmptyParts);
|
|
||||||
for (const QString &entry : entries) {
|
|
||||||
if (entry.startsWith("find: "))
|
|
||||||
continue;
|
|
||||||
const FilePath fp = FilePath::fromString(entry);
|
|
||||||
|
|
||||||
if (!callBack(fp.onDevice(filePath)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockerDevice::iterateDirectory(const FilePath &filePath,
|
void DockerDevice::iterateDirectory(const FilePath &filePath,
|
||||||
const std::function<bool(const FilePath &)> &callBack,
|
const std::function<bool(const FilePath &)> &callBack,
|
||||||
const FileFilter &filter) const
|
const FileFilter &filter) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(handlesFile(filePath), return);
|
QTC_ASSERT(handlesFile(filePath), return);
|
||||||
|
auto runInShell = [this](const CommandLine &cmd) { return d->outputForRunInShell(cmd); };
|
||||||
if (d->useFind()) {
|
FileUtils::iterateUnixDirectory(filePath, filter, &d->m_useFind, runInShell, callBack);
|
||||||
iterateWithFind(filePath, callBack, filter);
|
|
||||||
// d->m_useFind will be set to false if 'find' is not found. In this
|
|
||||||
// case fall back to 'ls' below.
|
|
||||||
if (d->useFind())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we do not have find - use ls as fallback
|
|
||||||
const QByteArray output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}});
|
|
||||||
const QStringList entries = QString::fromUtf8(output).split('\n', Qt::SkipEmptyParts);
|
|
||||||
FileUtils::iterateLsOutput(filePath, entries, filter, callBack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QByteArray> DockerDevice::fileContents(const FilePath &filePath,
|
std::optional<QByteArray> DockerDevice::fileContents(const FilePath &filePath,
|
||||||
|
|||||||
Reference in New Issue
Block a user