forked from qt-creator/qt-creator
Docker: Add Filepath::localSource()
FilePath::localSource can return a filepath that represents a local version of a remote file. It is used to let the debugger select the local version of a file when debugging a remote target. Change-Id: Ieb934ef0d454e8ff55e71df41dca825974d85da7 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -1588,6 +1588,16 @@ FilePath FilePath::resolvePath(const QString &tail) const
|
|||||||
return resolvePath(FilePath::fromString(tail));
|
return resolvePath(FilePath::fromString(tail));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected_str<FilePath> FilePath::localSource() const
|
||||||
|
{
|
||||||
|
if (!needsDevice())
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
QTC_ASSERT(s_deviceHooks.localSource,
|
||||||
|
return make_unexpected(Tr::tr("No 'localSource' device hook set.")));
|
||||||
|
return s_deviceHooks.localSource(*this);
|
||||||
|
}
|
||||||
|
|
||||||
// Cleans path part similar to QDir::cleanPath()
|
// Cleans path part similar to QDir::cleanPath()
|
||||||
// - directory separators normalized (that is, platform-native
|
// - directory separators normalized (that is, platform-native
|
||||||
// separators converted to "/") and redundant ones removed, and "."s and ".."s
|
// separators converted to "/") and redundant ones removed, and "."s and ".."s
|
||||||
|
@@ -238,6 +238,8 @@ public:
|
|||||||
[[nodiscard]] static int schemeAndHostLength(const QStringView path);
|
[[nodiscard]] static int schemeAndHostLength(const QStringView path);
|
||||||
|
|
||||||
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);
|
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);
|
||||||
|
//! Returns a filepath the represents the same file on a local drive
|
||||||
|
expected_str<FilePath> localSource() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ::tst_fileutils;
|
friend class ::tst_fileutils;
|
||||||
@@ -268,6 +270,7 @@ public:
|
|||||||
std::function<bool(const FilePath &, const FilePath &)> ensureReachable;
|
std::function<bool(const FilePath &, const FilePath &)> ensureReachable;
|
||||||
std::function<Environment(const FilePath &)> environment;
|
std::function<Environment(const FilePath &)> environment;
|
||||||
std::function<bool(const FilePath &left, const FilePath &right)> isSameDevice;
|
std::function<bool(const FilePath &left, const FilePath &right)> isSameDevice;
|
||||||
|
std::function<expected_str<FilePath>(const FilePath &)> localSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -1165,7 +1165,9 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
|||||||
showMessage("INVALID STOPPED REASON", LogWarning);
|
showMessage("INVALID STOPPED REASON", LogWarning);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilePath fileName = FilePath::fromString(fullName);
|
const FilePath onDevicePath = FilePath::fromString(fullName).onDevice(
|
||||||
|
runParameters().debugger.command.executable());
|
||||||
|
const FilePath fileName = onDevicePath.localSource().value_or(onDevicePath);
|
||||||
|
|
||||||
if (!nr.isEmpty() && frame.isValid()) {
|
if (!nr.isEmpty() && frame.isValid()) {
|
||||||
// Use opportunity to update the breakpoint marker position.
|
// Use opportunity to update the breakpoint marker position.
|
||||||
|
@@ -74,7 +74,8 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet
|
|||||||
frame.function = frameMi["function"].data();
|
frame.function = frameMi["function"].data();
|
||||||
frame.module = frameMi["module"].data();
|
frame.module = frameMi["module"].data();
|
||||||
const FilePath debugger = rp.debugger.command.executable();
|
const FilePath debugger = rp.debugger.command.executable();
|
||||||
frame.file = FilePath::fromString(frameMi["file"].data()).onDevice(debugger);
|
const FilePath onDevicePath = FilePath::fromString(frameMi["file"].data()).onDevice(debugger);
|
||||||
|
frame.file = onDevicePath.localSource().value_or(onDevicePath);
|
||||||
frame.line = frameMi["line"].toInt();
|
frame.line = frameMi["line"].toInt();
|
||||||
frame.address = frameMi["address"].toAddress();
|
frame.address = frameMi["address"].toAddress();
|
||||||
frame.context = frameMi["context"].data();
|
frame.context = frameMi["context"].data();
|
||||||
|
@@ -144,6 +144,7 @@ public:
|
|||||||
void changeMounts(QStringList newMounts);
|
void changeMounts(QStringList newMounts);
|
||||||
bool ensureReachable(const FilePath &other);
|
bool ensureReachable(const FilePath &other);
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
expected_str<FilePath> localSource(const FilePath &other) const;
|
||||||
|
|
||||||
QString containerId() { return m_container; }
|
QString containerId() { return m_container; }
|
||||||
DockerDeviceData data() { return m_data; }
|
DockerDeviceData data() { return m_data; }
|
||||||
@@ -828,6 +829,11 @@ bool DockerDevice::ensureReachable(const FilePath &other) const
|
|||||||
return d->ensureReachable(other.parentDir());
|
return d->ensureReachable(other.parentDir());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected_str<FilePath> DockerDevice::localSource(const Utils::FilePath &other) const
|
||||||
|
{
|
||||||
|
return d->localSource(other);
|
||||||
|
}
|
||||||
|
|
||||||
Environment DockerDevice::systemEnvironment() const
|
Environment DockerDevice::systemEnvironment() const
|
||||||
{
|
{
|
||||||
return d->environment();
|
return d->environment();
|
||||||
@@ -1125,6 +1131,27 @@ void DockerDevicePrivate::changeMounts(QStringList newMounts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected_str<FilePath> DockerDevicePrivate::localSource(const FilePath &other) const
|
||||||
|
{
|
||||||
|
const auto devicePath = FilePath::fromString(other.path());
|
||||||
|
for (const TemporaryMountInfo &info : m_temporaryMounts) {
|
||||||
|
if (devicePath.isChildOf(info.containerPath)) {
|
||||||
|
const FilePath relativePath = devicePath.relativeChildPath(info.containerPath);
|
||||||
|
return info.path.pathAppended(relativePath.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QString &mount : m_data.mounts) {
|
||||||
|
const FilePath mountPoint = FilePath::fromString(mount);
|
||||||
|
if (devicePath.isChildOf(mountPoint)) {
|
||||||
|
const FilePath relativePath = devicePath.relativeChildPath(mountPoint);
|
||||||
|
return mountPoint.pathAppended(relativePath.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_unexpected(Tr::tr("localSource: No mount point found for %1").arg(other.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
bool DockerDevicePrivate::ensureReachable(const FilePath &other)
|
bool DockerDevicePrivate::ensureReachable(const FilePath &other)
|
||||||
{
|
{
|
||||||
for (const QString &mount : m_data.mounts) {
|
for (const QString &mount : m_data.mounts) {
|
||||||
|
@@ -86,6 +86,7 @@ public:
|
|||||||
|
|
||||||
bool handlesFile(const Utils::FilePath &filePath) const override;
|
bool handlesFile(const Utils::FilePath &filePath) const override;
|
||||||
bool ensureReachable(const Utils::FilePath &other) const override;
|
bool ensureReachable(const Utils::FilePath &other) const override;
|
||||||
|
Utils::expected_str<Utils::FilePath> localSource(const Utils::FilePath &other) const override;
|
||||||
|
|
||||||
Utils::Environment systemEnvironment() const override;
|
Utils::Environment systemEnvironment() const override;
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
|
|
||||||
#include "idevicefactory.h"
|
#include "idevicefactory.h"
|
||||||
|
#include "projectexplorertr.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
@@ -414,6 +415,13 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
|
|||||||
return leftDevice == rightDevice;
|
return leftDevice == rightDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
deviceHooks.localSource = [](const FilePath &file) -> expected_str<FilePath> {
|
||||||
|
auto device = DeviceManager::deviceForPath(file);
|
||||||
|
if (!device)
|
||||||
|
return make_unexpected(Tr::tr("No device for path \"%1\"").arg(file.toUserOutput()));
|
||||||
|
return device->localSource(file);
|
||||||
|
};
|
||||||
|
|
||||||
deviceHooks.fileAccess = [](const FilePath &filePath) -> DeviceFileAccess * {
|
deviceHooks.fileAccess = [](const FilePath &filePath) -> DeviceFileAccess * {
|
||||||
if (!filePath.needsDevice())
|
if (!filePath.needsDevice())
|
||||||
return DesktopDeviceFileAccess::instance();
|
return DesktopDeviceFileAccess::instance();
|
||||||
|
@@ -10,11 +10,11 @@
|
|||||||
|
|
||||||
#include "../kit.h"
|
#include "../kit.h"
|
||||||
#include "../kitinformation.h"
|
#include "../kitinformation.h"
|
||||||
|
#include "../projectexplorertr.h"
|
||||||
|
#include "../target.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
|
|
||||||
#include <utils/devicefileaccess.h>
|
#include <utils/devicefileaccess.h>
|
||||||
#include <utils/displayname.h>
|
#include <utils/displayname.h>
|
||||||
#include <utils/icon.h>
|
#include <utils/icon.h>
|
||||||
@@ -630,6 +630,12 @@ bool IDevice::ensureReachable(const FilePath &other) const
|
|||||||
return handlesFile(other); // Some first approximation.
|
return handlesFile(other); // Some first approximation.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected_str<FilePath> IDevice::localSource(const Utils::FilePath &other) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(other);
|
||||||
|
return make_unexpected(Tr::tr("localSource() not implemented for this device type."));
|
||||||
|
}
|
||||||
|
|
||||||
bool IDevice::prepareForBuild(const Target *target)
|
bool IDevice::prepareForBuild(const Target *target)
|
||||||
{
|
{
|
||||||
Q_UNUSED(target)
|
Q_UNUSED(target)
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "idevicefwd.h"
|
#include "idevicefwd.h"
|
||||||
|
|
||||||
#include <utils/id.h>
|
#include <utils/id.h>
|
||||||
|
#include <utils/expected.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/tasktree.h>
|
#include <utils/tasktree.h>
|
||||||
@@ -215,6 +216,7 @@ public:
|
|||||||
virtual void aboutToBeRemoved() const {}
|
virtual void aboutToBeRemoved() const {}
|
||||||
|
|
||||||
virtual bool ensureReachable(const Utils::FilePath &other) const;
|
virtual bool ensureReachable(const Utils::FilePath &other) const;
|
||||||
|
virtual Utils::expected_str<Utils::FilePath> localSource(const Utils::FilePath &other) const;
|
||||||
|
|
||||||
virtual bool prepareForBuild(const Target *target);
|
virtual bool prepareForBuild(const Target *target);
|
||||||
virtual std::optional<Utils::FilePath> clangdExecutable() const;
|
virtual std::optional<Utils::FilePath> clangdExecutable() const;
|
||||||
|
Reference in New Issue
Block a user