Utils: Store Device::osType in settings

Change-Id: I41348be752598b7a8d1f1979764e7111cccc95a9
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-03-15 09:30:14 +01:00
parent af809b3a52
commit 29873068eb
13 changed files with 95 additions and 62 deletions

View File

@@ -269,12 +269,6 @@ bool DeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &targ
return false;
}
OsType DeviceFileAccess::osType(const FilePath &filePath) const
{
Q_UNUSED(filePath)
return OsTypeOther;
}
FilePath DeviceFileAccess::symLinkTarget(const FilePath &filePath) const
{
Q_UNUSED(filePath)
@@ -799,12 +793,6 @@ QByteArray DesktopDeviceFileAccess::fileId(const FilePath &filePath) const
return result;
}
OsType DesktopDeviceFileAccess::osType(const FilePath &filePath) const
{
Q_UNUSED(filePath)
return HostOsInfo::hostOs();
}
// UnixDeviceAccess
UnixDeviceFileAccess::~UnixDeviceFileAccess() = default;
@@ -1035,30 +1023,6 @@ expected_str<FilePath> UnixDeviceFileAccess::createTempFile(const FilePath &file
return newPath;
}
OsType UnixDeviceFileAccess::osType() const
{
if (m_osType)
return *m_osType;
const RunResult result = runInShell({"uname", {"-s"}, OsType::OsTypeLinux});
QTC_ASSERT(result.exitCode == 0, return OsTypeLinux);
const QString osName = QString::fromUtf8(result.stdOut).trimmed();
if (osName == "Darwin")
m_osType = OsTypeMac;
else if (osName == "Linux")
m_osType = OsTypeLinux;
else
m_osType = OsTypeOtherUnix;
return *m_osType;
}
OsType UnixDeviceFileAccess::osType(const FilePath &filePath) const
{
Q_UNUSED(filePath);
return osType();
}
QDateTime UnixDeviceFileAccess::lastModified(const FilePath &filePath) const
{
const RunResult result = runInShell(
@@ -1072,7 +1036,7 @@ QStringList UnixDeviceFileAccess::statArgs(const FilePath &filePath,
const QString &linuxFormat,
const QString &macFormat) const
{
return (osType() == OsTypeMac ? QStringList{"-f", macFormat} : QStringList{"-c", linuxFormat})
return (filePath.osType() == OsTypeMac ? QStringList{"-f", macFormat} : QStringList{"-c", linuxFormat})
<< "-L" << filePath.path();
}
@@ -1150,7 +1114,7 @@ FilePathInfo UnixDeviceFileAccess::filePathInfo(const FilePath &filePath) const
const RunResult stat = runInShell({"stat", args, OsType::OsTypeLinux});
return FileUtils::filePathInfoFromTriple(QString::fromLatin1(stat.stdOut),
osType() == OsTypeMac ? 8 : 16);
filePath.osType() == OsTypeMac ? 8 : 16);
}
// returns whether 'find' could be used.
@@ -1165,7 +1129,7 @@ bool UnixDeviceFileAccess::iterateWithFind(const FilePath &filePath,
// 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 statFormat = osType() == OsTypeMac
const QString statFormat = filePath.osType() == OsTypeMac
? QLatin1String("-f \"%p %m %z\"") : QLatin1String("-c \"%f %Y %s\"");
if (callBack.index() == 1)
@@ -1192,7 +1156,7 @@ bool UnixDeviceFileAccess::iterateWithFind(const FilePath &filePath,
if (entries.isEmpty())
return true;
const int modeBase = osType() == OsTypeMac ? 8 : 16;
const int modeBase = filePath.osType() == OsTypeMac ? 8 : 16;
const auto toFilePath =
[&filePath, &callBack, modeBase](const QString &entry) {

View File

@@ -45,7 +45,6 @@ protected:
const FilePath &target) const;
virtual bool renameFile(const FilePath &filePath, const FilePath &target) const;
virtual OsType osType(const FilePath &filePath) const;
virtual FilePath symLinkTarget(const FilePath &filePath) const;
virtual FilePathInfo filePathInfo(const FilePath &filePath) const;
virtual QDateTime lastModified(const FilePath &filePath) const;
@@ -100,7 +99,6 @@ protected:
expected_str<void> copyFile(const FilePath &filePath, const FilePath &target) const override;
bool renameFile(const FilePath &filePath, const FilePath &target) const override;
OsType osType(const FilePath &filePath) const override;
FilePath symLinkTarget(const FilePath &filePath) const override;
FilePathInfo filePathInfo(const FilePath &filePath) const override;
QDateTime lastModified(const FilePath &filePath) const override;
@@ -159,7 +157,6 @@ protected:
bool renameFile(const FilePath &filePath, const FilePath &target) const override;
FilePathInfo filePathInfo(const FilePath &filePath) const override;
OsType osType(const FilePath &filePath) const override;
FilePath symLinkTarget(const FilePath &filePath) const override;
QDateTime lastModified(const FilePath &filePath) const override;
QFile::Permissions permissions(const FilePath &filePath) const override;
@@ -194,14 +191,12 @@ private:
const FileFilter &filter,
QStringList *found) const;
Utils::OsType osType() const;
QStringList statArgs(const FilePath &filePath,
const QString &linuxFormat,
const QString &macFormat) const;
mutable bool m_tryUseFind = true;
mutable std::optional<bool> m_hasMkTemp;
mutable std::optional<Utils::OsType> m_osType;
};
} // Utils

View File

@@ -1566,7 +1566,11 @@ bool FilePath::setPermissions(QFile::Permissions permissions) const
OsType FilePath::osType() const
{
return fileAccess()->osType(*this);
if (!needsDevice())
return HostOsInfo::hostOs();
QTC_ASSERT(s_deviceHooks.osType, return HostOsInfo::hostOs());
return s_deviceHooks.osType(*this);
}
bool FilePath::removeFile() const

View File

@@ -291,6 +291,7 @@ public:
std::function<bool(const FilePath &left, const FilePath &right)> isSameDevice;
std::function<expected_str<FilePath>(const FilePath &)> localSource;
std::function<void(const FilePath &, const Environment &)> openTerminal;
std::function<OsType(const FilePath &)> osType;
};
// For testing

View File

@@ -14,6 +14,36 @@ namespace Utils {
// Add more as needed.
enum OsType { OsTypeWindows, OsTypeLinux, OsTypeMac, OsTypeOtherUnix, OsTypeOther };
inline QString osTypeToString(OsType osType)
{
switch (osType) {
case OsTypeWindows:
return "Windows";
case OsTypeLinux:
return "Linux";
case OsTypeMac:
return "Mac";
case OsTypeOtherUnix:
return "Other Unix";
case OsTypeOther:
default:
return "Other";
}
}
inline OsType osTypeFromString(const QString &string)
{
if (string == "Windows")
return OsTypeWindows;
if (string == "Linux")
return OsTypeLinux;
if (string == "Mac")
return OsTypeMac;
if (string == "Other Unix")
return OsTypeOtherUnix;
return OsTypeOther;
}
namespace OsSpecificAspects {
inline QString withExecutableSuffix(OsType osType, const QString &executable)

View File

@@ -126,7 +126,6 @@ public:
RunResult runInShell(const CommandLine &cmdLine,
const QByteArray &stdInData) const override;
QString mapToDevicePath(const QString &hostPath) const override;
OsType osType(const FilePath &filePath) const override;
DockerDevicePrivate *m_dev = nullptr;
};
@@ -377,12 +376,6 @@ QString DockerDeviceFileAccess::mapToDevicePath(const QString &hostPath) const
return newPath;
}
OsType DockerDeviceFileAccess::osType(const FilePath &filePath) const
{
QTC_ASSERT(m_dev, return UnixDeviceFileAccess::osType(filePath));
return m_dev->q->osType();
}
DockerDevice::DockerDevice(DockerSettings *settings, const DockerDeviceData &data)
: d(new DockerDevicePrivate(this, settings, data))
{

View File

@@ -443,6 +443,13 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
device->openTerminal(env, filePath);
};
deviceHooks.osType = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
if (!device)
return OsTypeLinux;
return device->osType();
};
DeviceProcessHooks processHooks;
processHooks.processImplHook = [](const FilePath &filePath) -> ProcessInterface * {

View File

@@ -17,6 +17,7 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/asynctask.h>
#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h>
@@ -182,6 +183,8 @@ void DeviceSettingsWidget::addDevice()
if (device.isNull())
return;
Utils::asyncRun([device] { device->checkOsType(); });
m_deviceManager->addDevice(device);
m_removeConfigButton->setEnabled(true);
m_configurationComboBox->setCurrentIndex(m_deviceManagerModel->indexOf(device));

View File

@@ -93,6 +93,7 @@ static Id newId()
const char DisplayNameKey[] = "Name";
const char TypeKey[] = "OsType";
const char ClientOsTypeKey[] = "ClientOsType";
const char IdKey[] = "InternalId";
const char OriginKey[] = "Origin";
const char MachineTypeKey[] = "Type";
@@ -426,6 +427,8 @@ void IDevice::fromMap(const QVariantMap &map)
d->type = typeFromMap(map);
d->displayName.fromMap(map, DisplayNameKey);
d->id = Id::fromSetting(map.value(QLatin1String(IdKey)));
d->osType = osTypeFromString(
map.value(QLatin1String(ClientOsTypeKey), osTypeToString(OsTypeLinux)).toString());
if (!d->id.isValid())
d->id = newId();
d->origin = static_cast<Origin>(map.value(QLatin1String(OriginKey), ManuallyAdded).toInt());
@@ -472,6 +475,7 @@ QVariantMap IDevice::toMap() const
QVariantMap map;
d->displayName.toMap(map, DisplayNameKey);
map.insert(QLatin1String(TypeKey), d->type.toString());
map.insert(QLatin1String(ClientOsTypeKey), osTypeToString(d->osType));
map.insert(QLatin1String(IdKey), d->id.toSetting());
map.insert(QLatin1String(OriginKey), d->origin);
@@ -504,9 +508,6 @@ IDevice::Ptr IDevice::clone() const
device->d->deviceState = d->deviceState;
device->d->deviceActions = d->deviceActions;
device->d->deviceIcons = d->deviceIcons;
// Os type is only set in the constructor, always to the same value.
// But make sure we notice if that changes in the future (which it shouldn't).
QTC_CHECK(device->d->osType == d->osType);
device->d->osType = d->osType;
device->fromMap(toMap());
return device;

View File

@@ -221,6 +221,8 @@ public:
virtual bool prepareForBuild(const Target *target);
virtual std::optional<Utils::FilePath> clangdExecutable() const;
virtual void checkOsType(){};
protected:
IDevice();

View File

@@ -305,6 +305,9 @@ public:
Environment getEnvironment();
void invalidateEnvironmentCache();
void checkOsType();
void queryOsType(std::function<RunResult(const CommandLine &)> run);
LinuxDevice *q = nullptr;
QThread m_shellThread;
ShellThreadHandler *m_handler = nullptr;
@@ -939,6 +942,12 @@ LinuxDevice::LinuxDevice()
}});
}
void LinuxDevice::_setOsType(Utils::OsType osType)
{
qCDebug(linuxDeviceLog) << "Setting OS type to" << osType << "for" << displayName();
IDevice::setOsType(osType);
}
LinuxDevice::~LinuxDevice()
{
delete d;
@@ -1045,6 +1054,23 @@ LinuxDevicePrivate::~LinuxDevicePrivate()
QMetaObject::invokeMethod(&m_shellThread, closeShell, Qt::BlockingQueuedConnection);
}
void LinuxDevicePrivate::queryOsType(std::function<RunResult(const CommandLine &)> runInShell)
{
const RunResult result = runInShell({"uname", {"-s"}, OsType::OsTypeLinux});
if (result.exitCode != 0)
q->_setOsType(OsTypeOtherUnix);
const QString osName = QString::fromUtf8(result.stdOut).trimmed();
if (osName == "Darwin")
q->_setOsType(OsTypeMac);
if (osName == "Linux")
q->_setOsType(OsTypeLinux);
}
void LinuxDevicePrivate::checkOsType()
{
queryOsType([this](const CommandLine &cmd) { return runInShell(cmd); });
}
// Call me with shell mutex locked
bool LinuxDevicePrivate::setupShell()
{
@@ -1058,6 +1084,10 @@ bool LinuxDevicePrivate::setupShell()
QMetaObject::invokeMethod(m_handler, [this, sshParameters] {
return m_handler->start(sshParameters);
}, Qt::BlockingQueuedConnection, &ok);
if (ok) {
queryOsType([this](const CommandLine &cmd) { return m_handler->runInShell(cmd); });
}
return ok;
}
@@ -1452,6 +1482,11 @@ LinuxDevicePrivate *LinuxDevice::connectionAccess() const
return d;
}
void LinuxDevice::checkOsType()
{
d->checkOsType();
}
namespace Internal {
// Factory

View File

@@ -42,11 +42,15 @@ public:
const ProjectExplorer::FileTransferSetupData &setup) const override;
class LinuxDevicePrivate *connectionAccess() const;
void checkOsType() override;
protected:
LinuxDevice();
void _setOsType(Utils::OsType osType);
class LinuxDevicePrivate *d;
friend class LinuxDevicePrivate;
};
namespace Internal {

View File

@@ -59,12 +59,6 @@ private slots:
m_fileSizeTestFile.writeFileContents(QByteArray(1024, 'a'));
}
void osType()
{
const auto osType = m_dfaPtr->osType({});
QCOMPARE(osType, HostOsInfo::hostOs());
}
void fileSize()
{
const auto size = m_dfaPtr->fileSize(m_fileSizeTestFile);