Utils: Replace FilePath::onDevice() by new FilePath::withMappedPath()

Basically a.onDevice(b) == b.withNewMappedPath(a), matching the order
of b.withNewPath(a).

Whether the (curretly docker-specific) path mapping is useful /there/, and
whether some of the calls are needed at all is dubious. I added some
FIXME and changed a few cases directly.

Change-Id: I7514736ce922f632f1f737bc496f6783389a42b6
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
hjk
2023-03-29 13:45:42 +02:00
parent 9956740905
commit 305ccfe259
27 changed files with 71 additions and 73 deletions

View File

@@ -204,11 +204,8 @@ expected_str<void> DeviceFileAccess::copyRecursively(const FilePath &src,
#ifdef UTILS_STATIC_LIBRARY
return copyRecursively_fallback(src, target);
#else
const FilePath tar = FilePath::fromString("tar").onDevice(target);
const FilePath targetTar = tar.searchInPath();
const FilePath sTar = FilePath::fromString("tar").onDevice(src);
const FilePath sourceTar = sTar.searchInPath();
const FilePath targetTar = target.withNewPath("tar").searchInPath();
const FilePath sourceTar = src.withNewPath("tar").searchInPath();
const bool isSrcOrTargetQrc = src.toFSPathString().startsWith(":/")
|| target.toFSPathString().startsWith(":/");
@@ -683,12 +680,13 @@ expected_str<FilePath> DesktopDeviceFileAccess::createTempFile(const FilePath &f
{
QTemporaryFile file(filePath.path());
file.setAutoRemove(false);
if (!file.open())
return make_unexpected(Tr::tr("Could not create temporary file in \"%1\" (%2)").arg(filePath.toUserOutput()).arg(file.errorString()));
return FilePath::fromString(file.fileName()).onDevice(filePath);
if (!file.open()) {
return make_unexpected(Tr::tr("Could not create temporary file in \"%1\" (%2)")
.arg(filePath.toUserOutput()).arg(file.errorString()));
}
return filePath.withNewPath(file.fileName());
}
QDateTime DesktopDeviceFileAccess::lastModified(const FilePath &filePath) const
{
return QFileInfo(filePath.path()).lastModified();
@@ -984,7 +982,7 @@ expected_str<FilePath> UnixDeviceFileAccess::createTempFile(const FilePath &file
.arg(filePath.toUserOutput(), QString::fromUtf8(result.stdErr)));
}
return FilePath::fromString(QString::fromUtf8(result.stdOut.trimmed())).onDevice(filePath);
return filePath.withNewPath(QString::fromUtf8(result.stdOut.trimmed()));
}
// Manually create a temporary/unique file.
@@ -1008,7 +1006,7 @@ expected_str<FilePath> UnixDeviceFileAccess::createTempFile(const FilePath &file
for (QChar *it = firstX.base(); it != std::end(tmplate); ++it) {
*it = chars[dist(*QRandomGenerator::global())];
}
newPath = FilePath::fromString(tmplate).onDevice(filePath);
newPath = filePath.withNewPath(tmplate);
if (--maxTries == 0) {
return make_unexpected(Tr::tr("Failed creating temporary file \"%1\" (too many tries)")
.arg(filePath.toUserOutput()));

View File

@@ -510,14 +510,14 @@ expected_str<FilePath> FilePath::tmpDir() const
if (needsDevice()) {
const Environment env = deviceEnvironment();
if (env.hasKey("TMPDIR"))
return FilePath::fromUserInput(env.value("TMPDIR")).onDevice(*this);
return withNewPath(env.value("TMPDIR")).cleanPath();
if (env.hasKey("TEMP"))
return FilePath::fromUserInput(env.value("TEMP")).onDevice(*this);
return withNewPath(env.value("TEMP")).cleanPath();
if (env.hasKey("TMP"))
return FilePath::fromUserInput(env.value("TMP")).onDevice(*this);
return withNewPath(env.value("TMP")).cleanPath();
if (osType() != OsTypeWindows)
return FilePath("/tmp").onDevice(*this);
return withNewPath("/tmp");
return make_unexpected(QString("Could not find temporary directory on device %1")
.arg(displayName()));
}
@@ -1416,30 +1416,31 @@ QString FilePath::calcRelativePath(const QString &absolutePath, const QString &a
}
/*!
Returns a path corresponding to the current object on the
same device as \a deviceTemplate. The FilePath needs to be local.
Returns a path corresponding to \a newPath object on the
same device as the current object.
This may involve device-specific translations like converting
windows style paths to unix style paths with suitable file
system case or handling of drive letters: C:/dev/src -> /c/dev/src
Example usage:
\code
localDir = FilePath("/tmp/workingdir");
executable = FilePath::fromUrl("docker://123/bin/ls")
realDir = localDir.onDevice(executable)
realDir = executable.withNewMappedPath(localDir)
assert(realDir == FilePath::fromUrl("docker://123/tmp/workingdir"))
\endcode
\param deviceTemplate A path from which the host and scheme is taken.
*/
FilePath FilePath::onDevice(const FilePath &deviceTemplate) const
FilePath FilePath::withNewMappedPath(const FilePath &newPath) const
{
isSameDevice(deviceTemplate);
const bool sameDevice = scheme() == deviceTemplate.scheme() && host() == deviceTemplate.host();
const bool sameDevice = newPath.scheme() == scheme() && newPath.host() == host();
if (sameDevice)
return *this;
return newPath;
// TODO: converting paths between different non local devices is still unsupported
QTC_CHECK(!needsDevice() || !deviceTemplate.needsDevice());
return fromParts(deviceTemplate.scheme(),
deviceTemplate.host(),
deviceTemplate.fileAccess()->mapToDevicePath(path()));
QTC_CHECK(!newPath.needsDevice() || !needsDevice());
FilePath res;
res.setParts(scheme(), host(), fileAccess()->mapToDevicePath(newPath.path()));
return res;
}
/*!
@@ -1486,8 +1487,8 @@ FilePath FilePath::searchInPath(const FilePaths &additionalDirs,
return *this;
FilePaths directories = deviceEnvironment().path();
if (needsDevice()) {
directories = Utils::transform(directories, [this](const FilePath &path) {
return path.onDevice(*this);
directories = Utils::transform(directories, [this](const FilePath &filePath) {
return withNewPath(filePath.path());
});
}
if (!additionalDirs.isEmpty()) {

View File

@@ -163,8 +163,8 @@ public:
[[nodiscard]] FilePath searchInDirectories(const FilePaths &dirs,
const FilePathPredicate &filter = {}) const;
[[nodiscard]] Environment deviceEnvironment() const;
[[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const;
[[nodiscard]] FilePath withNewPath(const QString &newPath) const;
[[nodiscard]] FilePath withNewMappedPath(const FilePath &newPath) const;
using IterateDirCallback
= std::variant<

View File

@@ -27,7 +27,7 @@ FilePath defaultShellForDevice(const FilePath &deviceRoot)
if (shell.isEmpty())
return shell;
return shell.onDevice(deviceRoot);
return deviceRoot.withNewMappedPath(shell);
}
class ExternalTerminalProcessImpl final : public TerminalInterface

View File

@@ -213,7 +213,7 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP
if (settings.clangdVersion() >= QVersionNumber(16))
cmd.addArg("--rename-file-limit=0");
if (!jsonDbDir.isEmpty())
cmd.addArg("--compile-commands-dir=" + jsonDbDir.onDevice(clangdExePath).path());
cmd.addArg("--compile-commands-dir=" + clangdExePath.withNewMappedPath(jsonDbDir).path());
if (clangdLogServer().isDebugEnabled())
cmd.addArgs({"--log=verbose", "--pretty"});
cmd.addArg("--use-dirty-headers");

View File

@@ -701,7 +701,7 @@ void CMakeBuildSettingsWidget::updateConfigureDetailsWidgetsSummary(
const FilePath buildDirectory = bc ? bc->buildDirectory() : ".";
cmd.addArgs({"-S", m_buildSystem->projectDirectory().path()});
cmd.addArgs({"-B", buildDirectory.onDevice(cmd.executable()).path()});
cmd.addArgs({"-B", cmd.executable().withNewMappedPath(buildDirectory).path()}); // FIXME: Just buildDirectory.path()
cmd.addArgs(configurationArguments);
params.setCommandLine(cmd);

View File

@@ -383,7 +383,7 @@ CommandLine CMakeBuildStep::cmakeCommand() const
if (buildConfiguration())
buildDirectory = buildConfiguration()->buildDirectory();
cmd.addArgs({"--build", buildDirectory.onDevice(cmd.executable()).path()});
cmd.addArgs({"--build", cmd.executable().withNewMappedPath(buildDirectory).path()});
cmd.addArg("--target");
cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) {

View File

@@ -1303,7 +1303,7 @@ MakeInstallCommand CMakeBuildSystem::makeInstallCommand(const FilePath &installR
buildDirectory = bc->buildDirectory();
cmd.command.addArg("--build");
cmd.command.addArg(buildDirectory.onDevice(cmd.command.executable()).path());
cmd.command.addArg(cmd.command.executable().withNewMappedPath(buildDirectory).path());
cmd.command.addArg("--target");
cmd.command.addArg(installTarget);

View File

@@ -74,7 +74,7 @@ CommandLine CMakeInstallStep::cmakeCommand() const
if (buildConfiguration())
buildDirectory = buildConfiguration()->buildDirectory();
cmd.addArgs({"--install", buildDirectory.onDevice(cmd.executable()).path()});
cmd.addArgs({"--install", cmd.executable().withNewMappedPath(buildDirectory).path()});
auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
if (bs && bs->isMultiConfigReader()) {

View File

@@ -1209,16 +1209,15 @@ Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const
FilePath tcCxxPath;
for (const CMakeConfigItem &i : config) {
// Do not use expand(QByteArray) as we cannot be sure the input is latin1
const FilePath expandedValue
= FilePath::fromString(k->macroExpander()->expand(QString::fromUtf8(i.value)));
const QString expandedValue = k->macroExpander()->expand(QString::fromUtf8(i.value));
if (i.key == CMAKE_QMAKE_KEY)
qmakePath = expandedValue.onDevice(cmake->cmakeExecutable());
qmakePath = cmake->cmakeExecutable().withNewPath(expandedValue);
else if (i.key == CMAKE_C_TOOLCHAIN_KEY)
tcCPath = expandedValue.onDevice(cmake->cmakeExecutable());
tcCPath = cmake->cmakeExecutable().withNewPath(expandedValue);
else if (i.key == CMAKE_CXX_TOOLCHAIN_KEY)
tcCxxPath = expandedValue.onDevice(cmake->cmakeExecutable());
tcCxxPath = cmake->cmakeExecutable().withNewPath(expandedValue);
else if (i.key == CMAKE_PREFIX_PATH_KEY)
qtInstallDirs = CMakeConfigItem::cmakeSplitValue(expandedValue.path());
qtInstallDirs = CMakeConfigItem::cmakeSplitValue(expandedValue);
}
Tasks result;
@@ -1259,7 +1258,7 @@ Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const
if (!tcC || !tcC->isValid()) {
addWarning(Tr::tr("CMake configuration has a path to a C compiler set, "
"even though the kit has no valid tool chain."));
} else if (tcCPath != tcC->compilerCommand() && tcCPath != tcC->compilerCommand().onDevice(tcCPath)) {
} else if (tcCPath != tcC->compilerCommand() && tcCPath != tcCPath.withNewMappedPath(tcC->compilerCommand())) {
addWarning(Tr::tr("CMake configuration has a path to a C compiler set "
"that does not match the compiler path "
"configured in the tool chain of the kit."));
@@ -1275,7 +1274,7 @@ Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const
if (!tcCxx || !tcCxx->isValid()) {
addWarning(Tr::tr("CMake configuration has a path to a C++ compiler set, "
"even though the kit has no valid tool chain."));
} else if (tcCxxPath != tcCxx->compilerCommand() && tcCxxPath != tcCxx->compilerCommand().onDevice(tcCxxPath)) {
} else if (tcCxxPath != tcCxx->compilerCommand() && tcCxxPath != tcCxxPath.withNewMappedPath(tcCxx->compilerCommand())) {
addWarning(Tr::tr("CMake configuration has a path to a C++ compiler set "
"that does not match the compiler path "
"configured in the tool chain of the kit."));

View File

@@ -67,8 +67,8 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
return;
}
const FilePath sourceDirectory = parameters.sourceDirectory.onDevice(cmakeExecutable);
const FilePath buildDirectory = parameters.buildDirectory.onDevice(cmakeExecutable);
const FilePath sourceDirectory = cmakeExecutable.withNewMappedPath(parameters.sourceDirectory);
const FilePath buildDirectory = cmakeExecutable.withNewMappedPath(parameters.buildDirectory);
if (!buildDirectory.exists()) {
const QString msg = ::CMakeProjectManager::Tr::tr(

View File

@@ -264,7 +264,7 @@ QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
continue;
const FilePath buildDir = haveLibrariesRelativeToBuildDirectory ? buildDirectory : currentBuildDir;
FilePath tmp = buildDir.resolvePath(FilePath::fromUserInput(part).onDevice(buildDir));
FilePath tmp = buildDir.resolvePath(buildDir.withNewPath(part));
if (f.role == "libraries")
tmp = tmp.parentDir();

View File

@@ -886,8 +886,8 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
Runnable inferior = runControl->runnable();
const FilePath &debuggerExecutable = m_runParameters.debugger.command.executable();
inferior.command.setExecutable(inferior.command.executable().onDevice(debuggerExecutable));
inferior.workingDirectory = inferior.workingDirectory.onDevice(debuggerExecutable);
inferior.command.setExecutable(debuggerExecutable.withNewMappedPath(inferior.command.executable()));
inferior.workingDirectory = debuggerExecutable.withNewMappedPath(inferior.workingDirectory);
// Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
inferior.workingDirectory = inferior.workingDirectory.normalizedPathName();
m_runParameters.inferior = inferior;

View File

@@ -74,7 +74,7 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet
frame.function = frameMi["function"].data();
frame.module = frameMi["module"].data();
const FilePath debugger = rp.debugger.command.executable();
const FilePath onDevicePath = FilePath::fromUserInput(frameMi["file"].data()).onDevice(debugger);
const FilePath onDevicePath = debugger.withNewPath(frameMi["file"].data()).cleanPath();
frame.file = onDevicePath.localSource().value_or(onDevicePath);
frame.line = frameMi["line"].toInt();
frame.address = frameMi["address"].toAddress();

View File

@@ -106,7 +106,7 @@ private:
CommandLine createFallbackCommand(const CommandLine &cmdLine)
{
CommandLine result = cmdLine;
result.setExecutable(cmdLine.executable().onDevice(m_devicePath));
result.setExecutable(m_devicePath.withNewPath(cmdLine.executable().path()));
return result;
}
@@ -497,7 +497,7 @@ CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
}
if (workDir && !workDir->isEmpty())
dockerCmd.addArgs({"-w", workDir->onDevice(q->rootPath()).nativePath()});
dockerCmd.addArgs({"-w", q->rootPath().withNewMappedPath(*workDir).nativePath()});
dockerCmd.addArg(m_container);

View File

@@ -2114,7 +2114,7 @@ FilePath Client::serverUriToHostPath(const LanguageServerProtocol::DocumentUri &
DocumentUri Client::hostPathToServerUri(const Utils::FilePath &path) const
{
return DocumentUri::fromFilePath(path, [&](const Utils::FilePath &clientPath) {
return clientPath.onDevice(d->m_serverDeviceTemplate);
return d->m_serverDeviceTemplate.withNewPath(clientPath.path());
});
}

View File

@@ -306,7 +306,7 @@ bool AbstractProcessStep::setupProcessParameters(ProcessParameters *params) cons
const bool looksGood = executable.isEmpty() || executable.ensureReachable(workingDirectory);
QTC_ASSERT(looksGood, return false);
params->setWorkingDirectory(workingDirectory.onDevice(executable));
params->setWorkingDirectory(executable.withNewPath(workingDirectory.path()));
return true;
}

View File

@@ -196,7 +196,7 @@ HeaderPaths GccToolChain::gccHeaderPaths(const FilePath &gcc,
}
const FilePath headerPath
= FilePath::fromString(QString::fromUtf8(line)).onDevice(gcc).canonicalPath();
= gcc.withNewPath(QString::fromUtf8(line)).canonicalPath();
if (!headerPath.isEmpty())
builtInHeaderPaths.append({headerPath, thisHeaderKind});

View File

@@ -391,7 +391,7 @@ Runnable RunConfiguration::runnable() const
Runnable r;
r.command = commandLine();
if (auto workingDirectoryAspect = aspect<WorkingDirectoryAspect>())
r.workingDirectory = workingDirectoryAspect->workingDirectory().onDevice(r.command.executable());
r.workingDirectory = r.command.executable().withNewPath(workingDirectoryAspect->workingDirectory().path());
if (auto environmentAspect = aspect<EnvironmentAspect>())
r.environment = environmentAspect->environment();
if (m_runnableModifier)

View File

@@ -624,7 +624,7 @@ FilePath ExecutableAspect::executable() const
: m_executable.filePath();
if (const IDevice::ConstPtr dev = executionDevice(m_target, m_selector))
exe = exe.onDevice(dev->rootPath());
exe = dev->rootPath().withNewMappedPath(exe);
return exe;
}

View File

@@ -63,7 +63,7 @@ PySideBuildStep::PySideBuildStep(BuildStepList *bsl, Id id)
setCommandLineProvider([this] { return CommandLine(m_pysideProject->filePath(), {"build"}); });
setWorkingDirectoryProvider([this] {
return target()->project()->projectDirectory().onDevice(m_pysideProject->filePath());
return m_pysideProject->filePath().withNewMappedPath(target()->project()->projectDirectory()); // FIXME: new path needed?
});
setEnvironmentModifier([this](Environment &env) {
env.prependOrSetPath(m_pysideProject->filePath().parentDir());

View File

@@ -216,7 +216,7 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Id id)
currentInterpreterChanged();
setRunnableModifier([](Runnable &r) {
r.workingDirectory = r.workingDirectory.onDevice(r.command.executable());
r.workingDirectory = r.command.executable().withNewMappedPath(r.workingDirectory); // FIXME: Needed?
});
connect(PySideInstaller::instance(), &PySideInstaller::pySideInstalled, this,
@@ -280,12 +280,12 @@ void PythonRunConfigurationPrivate::handlePySidePackageInfo(const PipPackageInfo
= OsSpecificAspects::withExecutableSuffix(python.osType(), "pyside6-uic");
for (const FilePath &file : files) {
if (file.fileName() == pySide6ProjectName) {
result.pySideProjectPath = location.resolvePath(file).onDevice(python);
result.pySideProjectPath = python.withNewMappedPath(location.resolvePath(file));
result.pySideProjectPath = result.pySideProjectPath.cleanPath();
if (!result.pySideUicPath.isEmpty())
return result;
} else if (file.fileName() == pySide6UicName) {
result.pySideUicPath = location.resolvePath(file).onDevice(python);
result.pySideUicPath = python.withNewMappedPath(location.resolvePath(file));
result.pySideUicPath = result.pySideUicPath.cleanPath();
if (!result.pySideProjectPath.isEmpty())
return result;

View File

@@ -1253,7 +1253,7 @@ void QtVersionPrivate::updateVersionInfo()
m_qmakeIsExecutable = true;
auto fileProperty = [this](const QByteArray &name) {
return FilePath::fromUserInput(qmakeProperty(name)).onDevice(m_qmakeCommand);
return m_qmakeCommand.withNewPath(qmakeProperty(name)).cleanPath();
};
m_data.prefix = fileProperty("QT_INSTALL_PREFIX");
@@ -1774,7 +1774,7 @@ FilePath QtVersionPrivate::mkspecDirectoryFromVersionInfo(const QHash<ProKey, Pr
QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc);
if (dataDir.isEmpty())
return FilePath();
return FilePath::fromUserInput(dataDir + "/mkspecs").onDevice(qmakeCommand);
return qmakeCommand.withNewPath(dataDir + "/mkspecs").cleanPath();
}
FilePath QtVersionPrivate::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo,

View File

@@ -821,7 +821,7 @@ class ShellThreadHandler : public QObject
CommandLine createFallbackCommand(const CommandLine &cmdLine) override
{
CommandLine result = cmdLine;
result.setExecutable(cmdLine.executable().onDevice(m_devicePath));
result.setExecutable(m_devicePath.withNewMappedPath(cmdLine.executable())); // Needed?
return result;
}

View File

@@ -145,7 +145,7 @@ bool MakeInstallStep::init()
if (!MakeStep::init())
return false;
const FilePath rootDir = installRoot().onDevice(makeCommand());
const FilePath rootDir = makeCommand().withNewPath(installRoot().path()); // FIXME: Needed?
if (rootDir.isEmpty()) {
emit addTask(BuildSystemTask(Task::Error, Tr::tr("You must provide an install root.")));
return false;
@@ -191,7 +191,7 @@ bool MakeInstallStep::init()
void MakeInstallStep::finish(ProcessResult result)
{
if (isSuccess(result)) {
const FilePath rootDir = installRoot().onDevice(makeCommand());
const FilePath rootDir = makeCommand().withNewPath(installRoot().path()); // FIXME: Needed?
m_deploymentData = DeploymentData();
m_deploymentData.setLocalInstallRoot(rootDir);

View File

@@ -201,7 +201,7 @@ void CallgrindToolRunner::run(Option option)
this, &CallgrindToolRunner::controllerProcessDone);
const FilePath control =
FilePath(CALLGRIND_CONTROL_BINARY).onDevice(m_valgrindRunnable.command.executable());
m_valgrindRunnable.command.executable().withNewPath(CALLGRIND_CONTROL_BINARY);
m_controllerProcess->setCommand({control, {toOptionString(option), QString::number(m_pid)}});
m_controllerProcess->setWorkingDirectory(m_valgrindRunnable.workingDirectory);
m_controllerProcess->setEnvironment(m_valgrindRunnable.environment);

View File

@@ -87,8 +87,8 @@ private slots:
void startsWithDriveLetter();
void startsWithDriveLetter_data();
void onDevice_data();
void onDevice();
void withNewMappedPath_data();
void withNewMappedPath();
void stringAppended();
void stringAppended_data();
@@ -1333,7 +1333,7 @@ void tst_filepath::startsWithDriveLetter()
QCOMPARE(path.startsWithDriveLetter(), expected);
}
void tst_filepath::onDevice_data()
void tst_filepath::withNewMappedPath_data()
{
QTest::addColumn<FilePath>("path");
QTest::addColumn<FilePath>("templatePath");
@@ -1350,13 +1350,13 @@ void tst_filepath::onDevice_data()
<< FilePath("/a/b") << FilePath("docker://1234/c/d") << FilePath("docker://1234/a/b");
}
void tst_filepath::onDevice()
void tst_filepath::withNewMappedPath()
{
QFETCH(FilePath, path);
QFETCH(FilePath, templatePath);
QFETCH(FilePath, expected);
QCOMPARE(path.onDevice(templatePath), expected);
QCOMPARE(templatePath.withNewMappedPath(path), expected);
}
void tst_filepath::stringAppended_data()