Utils: Use a structure to specify several QtcProcess device hooks

... and add a QtcProcess::systemEnvironmentForBinary(filePath)
redirecting to IDevice::systemEnvironment() of the device implicitly
given by filePath. A device implied by e.g. a qmake binary or a compiler
binary is a common scenario.

Change-Id: Ieb2c724ae66f1a1752132e4e4648a604390ca369
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2021-05-26 17:40:57 +02:00
parent 125cdcc3a0
commit 6de05306d6
3 changed files with 47 additions and 17 deletions

View File

@@ -73,7 +73,7 @@ enum { defaultMaxHangTimerCount = 10 };
static Q_LOGGING_CATEGORY(processLog, "qtc.utils.synchronousprocess", QtWarningMsg);
static std::function<void(QtcProcess &)> s_remoteRunProcessHook;
static DeviceProcessHooks s_deviceHooks;
// Data for one channel buffer (stderr/stdout)
class ChannelBuffer
@@ -225,8 +225,8 @@ void QtcProcess::start()
QTC_CHECK(d->m_writeData.isEmpty()); // FIXME: Use it.
if (d->m_commandLine.executable().needsDevice()) {
QTC_ASSERT(s_remoteRunProcessHook, return);
s_remoteRunProcessHook(*this);
QTC_ASSERT(s_deviceHooks.startProcessHook, return);
s_deviceHooks.startProcessHook(*this);
return;
}
@@ -336,9 +336,9 @@ void QtcProcess::setDisableUnixTerminal()
d->m_disableUnixTerminal = true;
}
void QtcProcess::setRemoteStartProcessHook(const std::function<void(QtcProcess &)> &hook)
void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks)
{
s_remoteRunProcessHook = hook;
s_deviceHooks = hooks;
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@@ -561,6 +561,16 @@ QString QtcProcess::locateBinary(const QString &path, const QString &binary)
return QString();
}
Environment QtcProcess::systemEnvironmentForBinary(const FilePath &filePath)
{
if (filePath.needsDevice()) {
QTC_ASSERT(s_deviceHooks.systemEnvironmentForBinary, return {});
return s_deviceHooks.systemEnvironmentForBinary(filePath);
}
return Environment::systemEnvironment();
}
QString QtcProcess::locateBinary(const QString &binary)
{
const QByteArray path = qgetenv("PATH");

View File

@@ -41,9 +41,17 @@ namespace Utils {
class CommandLine;
class Environment;
class QtcProcess;
namespace Internal { class QtcProcessPrivate; }
class DeviceProcessHooks
{
public:
std::function<void(QtcProcess &)> startProcessHook;
std::function<Environment(const FilePath &)> systemEnvironmentForBinary;
};
class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess
{
Q_OBJECT
@@ -92,7 +100,7 @@ public:
void setStdOutCallback(const std::function<void(const QString &)> &callback);
void setStdErrCallback(const std::function<void(const QString &)> &callback);
static void setRemoteStartProcessHook(const std::function<void (QtcProcess &)> &hook);
static void setRemoteProcessHooks(const DeviceProcessHooks &hooks);
void setOpenMode(OpenMode mode);
@@ -123,6 +131,8 @@ public:
static QString locateBinary(const QString &binary);
static QString locateBinary(const QString &path, const QString &binary);
static Environment systemEnvironmentForBinary(const FilePath &filePath);
private:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void setupChildProcess() override;

View File

@@ -363,59 +363,69 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
this, &DeviceManager::save);
DeviceFileHooks hooks;
DeviceFileHooks deviceHooks;
hooks.isExecutableFile = [](const FilePath &filePath) {
deviceHooks.isExecutableFile = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return false);
return device->isExecutableFile(filePath);
};
hooks.isReadableFile = [](const FilePath &filePath) {
deviceHooks.isReadableFile = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return false);
return device->isReadableFile(filePath);
};
hooks.isReadableDir = [](const FilePath &filePath) {
deviceHooks.isReadableDir = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return false);
return device->isReadableDirectory(filePath);
};
hooks.isWritableDir = [](const FilePath &filePath) {
deviceHooks.isWritableDir = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return false);
return device->isWritableDirectory(filePath);
};
hooks.createDir = [](const FilePath &filePath) {
deviceHooks.createDir = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return false);
return device->createDirectory(filePath);
};
hooks.dirEntries = [](const FilePath &filePath,
deviceHooks.dirEntries = [](const FilePath &filePath,
const QStringList &nameFilters, QDir::Filters filters) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return FilePaths());
return device->directoryEntries(filePath, nameFilters, filters);
};
hooks.fileContents = [](const FilePath &filePath, int maxSize) {
deviceHooks.fileContents = [](const FilePath &filePath, int maxSize) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return QByteArray());
return device->fileContents(filePath, maxSize);
};
FilePath::setDeviceFileHooks(hooks);
FilePath::setDeviceFileHooks(deviceHooks);
QtcProcess::setRemoteStartProcessHook([](QtcProcess &process) {
DeviceProcessHooks processHooks;
processHooks.startProcessHook = [](QtcProcess &process) {
FilePath filePath = process.commandLine().executable();
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return);
device->runProcess(process);
});
};
processHooks.systemEnvironmentForBinary = [](const FilePath &filePath) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return Environment());
return device->systemEnvironment();
};
QtcProcess::setRemoteProcessHooks(processHooks);
}
DeviceManager::~DeviceManager()