FilePath: Return optional bytearray from device hooks

For differentiating between "error" and "empty file".

Change-Id: I1806bb7386f5e7db28489f9f7e685648bfc20110
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Eike Ziller
2022-09-09 14:25:36 +02:00
parent f5c22a42ae
commit e7ddd8a5b7
12 changed files with 67 additions and 35 deletions

View File

@@ -534,7 +534,6 @@ std::optional<QByteArray> FilePath::fileContents(qint64 maxSize, qint64 offset)
{ {
if (needsDevice()) { if (needsDevice()) {
QTC_ASSERT(s_deviceHooks.fileContents, return {}); QTC_ASSERT(s_deviceHooks.fileContents, return {});
// TODO change hooks to return optional byte array
return s_deviceHooks.fileContents(*this, maxSize, offset); return s_deviceHooks.fileContents(*this, maxSize, offset);
} }

View File

@@ -246,7 +246,7 @@ public:
std::function<void(const FilePath &, std::function<void(const FilePath &,
const std::function<bool(const FilePath &)> &, // Abort on 'false' return. const std::function<bool(const FilePath &)> &, // Abort on 'false' return.
const FileFilter &)> iterateDirectory; const FileFilter &)> iterateDirectory;
std::function<QByteArray(const FilePath &, qint64, qint64)> fileContents; std::function<std::optional<QByteArray>(const FilePath &, qint64, qint64)> fileContents;
std::function<bool(const FilePath &, const QByteArray &)> writeFileContents; std::function<bool(const FilePath &, const QByteArray &)> writeFileContents;
std::function<QDateTime(const FilePath &)> lastModified; std::function<QDateTime(const FilePath &)> lastModified;
std::function<QFile::Permissions(const FilePath &)> permissions; std::function<QFile::Permissions(const FilePath &)> permissions;

View File

@@ -958,7 +958,9 @@ void DockerDevice::iterateDirectory(const FilePath &filePath,
FileUtils::iterateLsOutput(filePath, entries, filter, callBack); FileUtils::iterateLsOutput(filePath, entries, filter, callBack);
} }
QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const std::optional<QByteArray> DockerDevice::fileContents(const FilePath &filePath,
qint64 limit,
qint64 offset) const
{ {
QTC_ASSERT(handlesFile(filePath), return {}); QTC_ASSERT(handlesFile(filePath), return {});
updateContainerAccess(); updateContainerAccess();
@@ -976,6 +978,8 @@ QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qi
proc.start(); proc.start();
proc.waitForFinished(); proc.waitForFinished();
if (proc.result() != ProcessResult::FinishedWithSuccess)
return {};
QByteArray output = proc.readAllStandardOutput(); QByteArray output = proc.readAllStandardOutput();
return output; return output;
} }

View File

@@ -80,7 +80,9 @@ public:
void iterateDirectory(const Utils::FilePath &filePath, void iterateDirectory(const Utils::FilePath &filePath,
const std::function<bool(const Utils::FilePath &)> &callBack, const std::function<bool(const Utils::FilePath &)> &callBack,
const Utils::FileFilter &filter) const override; const Utils::FileFilter &filter) const override;
QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override; std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit,
qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override; bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
QDateTime lastModified(const Utils::FilePath &filePath) const override; QDateTime lastModified(const Utils::FilePath &filePath) const override;
qint64 fileSize(const Utils::FilePath &filePath) const override; qint64 fileSize(const Utils::FilePath &filePath) const override;

View File

@@ -265,10 +265,12 @@ FilePath DesktopDevice::symLinkTarget(const FilePath &filePath) const
return filePath.symLinkTarget(); return filePath.symLinkTarget();
} }
QByteArray DesktopDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const std::optional<QByteArray> DesktopDevice::fileContents(const FilePath &filePath,
qint64 limit,
qint64 offset) const
{ {
QTC_ASSERT(handlesFile(filePath), return {}); QTC_ASSERT(handlesFile(filePath), return {});
return filePath.fileContents(limit, offset).value_or(QByteArray()); return filePath.fileContents(limit, offset);
} }
bool DesktopDevice::writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const bool DesktopDevice::writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const

View File

@@ -52,7 +52,9 @@ public:
void iterateDirectory(const Utils::FilePath &filePath, void iterateDirectory(const Utils::FilePath &filePath,
const std::function<bool(const Utils::FilePath &)> &callBack, const std::function<bool(const Utils::FilePath &)> &callBack,
const Utils::FileFilter &filter) const override; const Utils::FileFilter &filter) const override;
QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override; std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit,
qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override; bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
qint64 fileSize(const Utils::FilePath &filePath) const override; qint64 fileSize(const Utils::FilePath &filePath) const override;
QFile::Permissions permissions(const Utils::FilePath &filePath) const override; QFile::Permissions permissions(const Utils::FilePath &filePath) const override;

View File

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

View File

@@ -362,7 +362,9 @@ void IDevice::iterateDirectory(const FilePath &filePath,
QTC_CHECK(false); QTC_CHECK(false);
} }
QByteArray IDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const std::optional<QByteArray> IDevice::fileContents(const FilePath &filePath,
qint64 limit,
qint64 offset) const
{ {
Q_UNUSED(filePath); Q_UNUSED(filePath);
Q_UNUSED(limit); Q_UNUSED(limit);
@@ -371,9 +373,10 @@ QByteArray IDevice::fileContents(const FilePath &filePath, qint64 limit, qint64
return {}; return {};
} }
void IDevice::asyncFileContents(const Continuation<QByteArray> &cont, void IDevice::asyncFileContents(const Continuation<std::optional<QByteArray>> &cont,
const FilePath &filePath, const FilePath &filePath,
qint64 limit, qint64 offset) const qint64 limit,
qint64 offset) const
{ {
cont(fileContents(filePath, limit, offset)); cont(fileContents(filePath, limit, offset));
} }

View File

@@ -237,7 +237,7 @@ public:
virtual void iterateDirectory(const Utils::FilePath &filePath, virtual void iterateDirectory(const Utils::FilePath &filePath,
const std::function<bool(const Utils::FilePath &)> &callBack, const std::function<bool(const Utils::FilePath &)> &callBack,
const Utils::FileFilter &filter) const; const Utils::FileFilter &filter) const;
virtual QByteArray fileContents(const Utils::FilePath &filePath, virtual std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit, qint64 limit,
qint64 offset) const; qint64 offset) const;
virtual bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const; virtual bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const;
@@ -253,9 +253,10 @@ public:
virtual void aboutToBeRemoved() const {} virtual void aboutToBeRemoved() const {}
virtual void asyncFileContents(const Continuation<QByteArray> &cont, virtual void asyncFileContents(const Continuation<std::optional<QByteArray>> &cont,
const Utils::FilePath &filePath, const Utils::FilePath &filePath,
qint64 limit, qint64 offset) const; qint64 limit,
qint64 offset) const;
virtual void asyncWriteFileContents(const Continuation<bool> &cont, virtual void asyncWriteFileContents(const Continuation<bool> &cont,
const Utils::FilePath &filePath, const Utils::FilePath &filePath,
const QByteArray &data) const; const QByteArray &data) const;

View File

@@ -361,7 +361,7 @@ public:
bool setupShell(); bool setupShell();
bool runInShell(const CommandLine &cmd, const QByteArray &data = {}); bool runInShell(const CommandLine &cmd, const QByteArray &data = {});
QByteArray outputForRunInShell(const CommandLine &cmd); std::optional<QByteArray> outputForRunInShell(const CommandLine &cmd);
void attachToSharedConnection(SshConnectionHandle *connectionHandle, void attachToSharedConnection(SshConnectionHandle *connectionHandle,
const SshParameters &sshParameters); const SshParameters &sshParameters);
@@ -814,10 +814,13 @@ public:
} }
// Call me with shell mutex locked // Call me with shell mutex locked
QByteArray outputForRunInShell(const CommandLine &cmd) std::optional<QByteArray> outputForRunInShell(const CommandLine &cmd)
{ {
QTC_ASSERT(m_shell, return {}); QTC_ASSERT(m_shell, return {});
return m_shell->outputForRunInShell(cmd).stdOut; const DeviceShell::RunResult result = m_shell->outputForRunInShell(cmd);
if (result.exitCode == 0)
return result.stdOut;
return {};
} }
void setSshParameters(const SshParameters &sshParameters) void setSshParameters(const SshParameters &sshParameters)
@@ -1104,7 +1107,7 @@ bool LinuxDevicePrivate::runInShell(const CommandLine &cmd, const QByteArray &da
return m_handler->runInShell(cmd, data); return m_handler->runInShell(cmd, data);
} }
QByteArray LinuxDevicePrivate::outputForRunInShell(const CommandLine &cmd) std::optional<QByteArray> LinuxDevicePrivate::outputForRunInShell(const CommandLine &cmd)
{ {
QMutexLocker locker(&m_shellMutex); QMutexLocker locker(&m_shellMutex);
DEBUG(cmd); DEBUG(cmd);
@@ -1237,7 +1240,8 @@ bool LinuxDevice::renameFile(const FilePath &filePath, const FilePath &target) c
QDateTime LinuxDevice::lastModified(const FilePath &filePath) const QDateTime LinuxDevice::lastModified(const FilePath &filePath) const
{ {
QTC_ASSERT(handlesFile(filePath), return {}); QTC_ASSERT(handlesFile(filePath), return {});
const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%Y", filePath.path()}}); const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%Y", filePath.path()}})
.value_or(QByteArray());
const qint64 secs = output.toLongLong(); const qint64 secs = output.toLongLong();
const QDateTime dt = QDateTime::fromSecsSinceEpoch(secs, Qt::UTC); const QDateTime dt = QDateTime::fromSecsSinceEpoch(secs, Qt::UTC);
return dt; return dt;
@@ -1246,7 +1250,8 @@ QDateTime LinuxDevice::lastModified(const FilePath &filePath) const
FilePath LinuxDevice::symLinkTarget(const FilePath &filePath) const FilePath LinuxDevice::symLinkTarget(const FilePath &filePath) const
{ {
QTC_ASSERT(handlesFile(filePath), return {}); QTC_ASSERT(handlesFile(filePath), return {});
const QByteArray output = d->outputForRunInShell({"readlink", {"-n", "-e", filePath.path()}}); const QByteArray output = d->outputForRunInShell({"readlink", {"-n", "-e", filePath.path()}})
.value_or(QByteArray());
const QString out = QString::fromUtf8(output.data(), output.size()); const QString out = QString::fromUtf8(output.data(), output.size());
return output.isEmpty() ? FilePath() : filePath.withNewPath(out); return output.isEmpty() ? FilePath() : filePath.withNewPath(out);
} }
@@ -1254,7 +1259,8 @@ FilePath LinuxDevice::symLinkTarget(const FilePath &filePath) const
qint64 LinuxDevice::fileSize(const FilePath &filePath) const qint64 LinuxDevice::fileSize(const FilePath &filePath) const
{ {
QTC_ASSERT(handlesFile(filePath), return -1); QTC_ASSERT(handlesFile(filePath), return -1);
const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%s", filePath.path()}}); const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%s", filePath.path()}})
.value_or(QByteArray());
return output.toLongLong(); return output.toLongLong();
} }
@@ -1264,7 +1270,7 @@ qint64 LinuxDevice::bytesAvailable(const FilePath &filePath) const
CommandLine cmd("df", {"-k"}); CommandLine cmd("df", {"-k"});
cmd.addArg(filePath.path()); cmd.addArg(filePath.path());
cmd.addArgs("|tail -n 1 |sed 's/ */ /g'|cut -d ' ' -f 4", CommandLine::Raw); cmd.addArgs("|tail -n 1 |sed 's/ */ /g'|cut -d ' ' -f 4", CommandLine::Raw);
const QByteArray output = d->outputForRunInShell(cmd); const QByteArray output = d->outputForRunInShell(cmd).value_or(QByteArray());
bool ok = false; bool ok = false;
const qint64 size = output.toLongLong(&ok); const qint64 size = output.toLongLong(&ok);
if (ok) if (ok)
@@ -1275,7 +1281,8 @@ qint64 LinuxDevice::bytesAvailable(const FilePath &filePath) const
QFileDevice::Permissions LinuxDevice::permissions(const FilePath &filePath) const QFileDevice::Permissions LinuxDevice::permissions(const FilePath &filePath) const
{ {
QTC_ASSERT(handlesFile(filePath), return {}); QTC_ASSERT(handlesFile(filePath), return {});
const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%a", filePath.path()}}); const QByteArray output = d->outputForRunInShell({"stat", {"-L", "-c", "%a", filePath.path()}})
.value_or(QByteArray());
const uint bits = output.toUInt(nullptr, 8); const uint bits = output.toUInt(nullptr, 8);
QFileDevice::Permissions perm = {}; QFileDevice::Permissions perm = {};
#define BIT(n, p) if (bits & (1<<n)) perm |= QFileDevice::p #define BIT(n, p) if (bits & (1<<n)) perm |= QFileDevice::p
@@ -1305,12 +1312,15 @@ void LinuxDevice::iterateDirectory(const FilePath &filePath,
{ {
QTC_ASSERT(handlesFile(filePath), return); QTC_ASSERT(handlesFile(filePath), return);
// if we do not have find - use ls as fallback // if we do not have find - use ls as fallback
const QByteArray output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}}); const QByteArray output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}})
.value_or(QByteArray());
const QStringList entries = QString::fromUtf8(output).split('\n', Qt::SkipEmptyParts); const QStringList entries = QString::fromUtf8(output).split('\n', Qt::SkipEmptyParts);
FileUtils::iterateLsOutput(filePath, entries, filter, callBack); FileUtils::iterateLsOutput(filePath, entries, filter, callBack);
} }
QByteArray LinuxDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const std::optional<QByteArray> LinuxDevice::fileContents(const FilePath &filePath,
qint64 limit,
qint64 offset) const
{ {
QTC_ASSERT(handlesFile(filePath), return {}); QTC_ASSERT(handlesFile(filePath), return {});
QString args = "if=" + filePath.path() + " status=none"; QString args = "if=" + filePath.path() + " status=none";
@@ -1320,8 +1330,12 @@ QByteArray LinuxDevice::fileContents(const FilePath &filePath, qint64 limit, qin
} }
CommandLine cmd(FilePath::fromString("dd"), args, CommandLine::Raw); CommandLine cmd(FilePath::fromString("dd"), args, CommandLine::Raw);
const QByteArray output = d->outputForRunInShell(cmd); const std::optional<QByteArray> output = d->outputForRunInShell(cmd);
DEBUG(output << QByteArray::fromHex(output)); if (output) {
DEBUG(*output << QByteArray::fromHex(*output));
} else {
DEBUG("fileContents failed");
}
return output; return output;
} }

View File

@@ -54,7 +54,9 @@ public:
void iterateDirectory(const Utils::FilePath &filePath, void iterateDirectory(const Utils::FilePath &filePath,
const std::function<bool(const Utils::FilePath &)> &callBack, const std::function<bool(const Utils::FilePath &)> &callBack,
const Utils::FileFilter &filter) const override; const Utils::FileFilter &filter) const override;
QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override; std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit,
qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override; bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
QDateTime lastModified(const Utils::FilePath &filePath) const override; QDateTime lastModified(const Utils::FilePath &filePath) const override;
Utils::ProcessInterface *createProcessInterface() const override; Utils::ProcessInterface *createProcessInterface() const override;

View File

@@ -59,8 +59,8 @@ void tst_fsengine::initTestCase()
DeviceFileHooks &deviceHooks = DeviceFileHooks::instance(); DeviceFileHooks &deviceHooks = DeviceFileHooks::instance();
deviceHooks.fileContents = deviceHooks.fileContents =
[](const FilePath &path, qint64 maxSize, qint64 offset) -> QByteArray { [](const FilePath &path, qint64 maxSize, qint64 offset) -> std::optional<QByteArray> {
return FilePath::fromString(path.path()).fileContents(maxSize, offset).value_or(QByteArray()); return FilePath::fromString(path.path()).fileContents(maxSize, offset);
}; };
deviceHooks.isExecutableFile = [](const FilePath &filePath) { deviceHooks.isExecutableFile = [](const FilePath &filePath) {