diff --git a/src/libs/utils/terminalhooks.cpp b/src/libs/utils/terminalhooks.cpp index 3bda25b109c..f1420755c59 100644 --- a/src/libs/utils/terminalhooks.cpp +++ b/src/libs/utils/terminalhooks.cpp @@ -17,6 +17,9 @@ FilePath defaultShellForDevice(const FilePath &deviceRoot) return deviceRoot.withNewPath("cmd.exe").searchInPath(); const Environment env = deviceRoot.deviceEnvironment(); + if (!env.hasChanges()) + return {}; + FilePath shell = FilePath::fromUserInput(env.value_or("SHELL", "/bin/sh")); if (!shell.isAbsolutePath()) @@ -32,7 +35,6 @@ class HooksPrivate { public: HooksPrivate() - : m_getTerminalCommandsForDevicesHook([] { return QList{}; }) { auto openTerminal = [](const OpenTerminalParameters ¶meters) { DeviceFileHooks::instance().openTerminal(parameters.workingDirectory.value_or( @@ -79,8 +81,6 @@ public: return m_openTerminal; } - Hooks::GetTerminalCommandsForDevicesHook m_getTerminalCommandsForDevicesHook; - private: Hooks::OpenTerminal m_openTerminal; Hooks::CreateTerminalProcessInterface m_createTerminalProcessInterface; @@ -111,11 +111,6 @@ ProcessInterface *Hooks::createTerminalProcessInterface() const return d->createTerminalProcessInterface()(); } -Hooks::GetTerminalCommandsForDevicesHook &Hooks::getTerminalCommandsForDevicesHook() -{ - return d->m_getTerminalCommandsForDevicesHook; -} - void Hooks::addCallbackSet(const QString &name, const CallbackSet &callbackSet) { d->addCallbackSet(name, callbackSet); diff --git a/src/libs/utils/terminalhooks.h b/src/libs/utils/terminalhooks.h index 02e37e84972..f5b55111c1e 100644 --- a/src/libs/utils/terminalhooks.h +++ b/src/libs/utils/terminalhooks.h @@ -85,14 +85,10 @@ public: CreateTerminalProcessInterface createTerminalProcessInterface; }; - using GetTerminalCommandsForDevicesHook = Hook>; - public: static Hooks &instance(); ~Hooks(); - GetTerminalCommandsForDevicesHook &getTerminalCommandsForDevicesHook(); - void openTerminal(const OpenTerminalParameters ¶meters) const; ProcessInterface *createTerminalProcessInterface() const; diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index aa017df46b0..f783ea18139 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -465,22 +465,6 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique QList { - QList result; - for (const IDevice::ConstPtr device : d->devices) { - if (device->type() == Constants::DESKTOP_DEVICE_TYPE) - continue; - - const FilePath shell = Terminal::defaultShellForDevice(device->rootPath()); - - if (!shell.isEmpty()) - result << Terminal::NameAndCommandLine{device->displayName(), - CommandLine{shell, {}}}; - } - return result; - }); } DeviceManager::~DeviceManager() @@ -497,6 +481,14 @@ IDevice::ConstPtr DeviceManager::deviceAt(int idx) const return d->devices.at(idx); } +void DeviceManager::forEachDevice(const std::function &func) const +{ + const QList devices = d->deviceList(); + + for (const IDevice::Ptr &device : devices) + func(device); +} + IDevice::Ptr DeviceManager::mutableDevice(Id id) const { const int index = d->indexForId(id); diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.h b/src/plugins/projectexplorer/devicesupport/devicemanager.h index 213624971b8..ce12ccf1b83 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.h +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.h @@ -35,6 +35,8 @@ public: int deviceCount() const; IDevice::ConstPtr deviceAt(int index) const; + void forEachDevice(const std::function &) const; + IDevice::ConstPtr find(Utils::Id id) const; IDevice::ConstPtr defaultDevice(Utils::Id deviceType) const; bool hasDevice(const QString &name) const; diff --git a/src/plugins/terminal/shellmodel.cpp b/src/plugins/terminal/shellmodel.cpp index 0cc58f1fe6c..a9667c95e13 100644 --- a/src/plugins/terminal/shellmodel.cpp +++ b/src/plugins/terminal/shellmodel.cpp @@ -3,6 +3,9 @@ #include "shellmodel.h" +#include +#include + #include #include #include @@ -138,11 +141,10 @@ ShellModelPrivate::ShellModelPrivate() }); // ... and filter out non-existing shells. - localShells = Utils::transform( - Utils::filtered(shells, [](const FilePath &shell) {return shell.exists(); }), - [&iconProvider](const FilePath &shell) { - return ShellItemBuilder(iconProvider, shell).item(); - }); + localShells = Utils::transform(Utils::filtered(shells, &FilePath::exists), + [&iconProvider](const FilePath &shell) { + return ShellItemBuilder(iconProvider, shell).item(); + }); } } @@ -161,14 +163,15 @@ QList ShellModel::local() const QList ShellModel::remote() const { - const auto deviceCmds = Utils::Terminal::Hooks::instance().getTerminalCommandsForDevicesHook()(); + QList result; - const QList deviceItems = Utils::transform( - deviceCmds, [](const Utils::Terminal::NameAndCommandLine &item) -> ShellModelItem { - return ShellModelItem{item.name, {item.commandLine}}; + ProjectExplorer::DeviceManager::instance()->forEachDevice( + [&result](const QSharedPointer &device) { + if (device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + result << ShellModelItem{device->displayName(), {{device->rootPath(), {}}}}; }); - return deviceItems; + return result; } } // namespace Terminal::Internal diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index 4b06c353433..326ed523915 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -82,6 +83,33 @@ void TerminalWidget::setupPty() CommandLine shellCommand = m_openParameters.shellCommand.value_or( CommandLine{settings().shell(), settings().shellArguments(), CommandLine::Raw}); + if (shellCommand.executable().isRootPath()) { + writeToTerminal(Tr::tr("Connecting ...\r\n").toUtf8(), true); + // We still have to find the shell to start ... + m_findShellWatcher.reset(new QFutureWatcher()); + connect(m_findShellWatcher.get(), &QFutureWatcher::finished, this, [this] { + const FilePath result = m_findShellWatcher->result(); + if (!result.isEmpty()) { + m_openParameters.shellCommand->setExecutable(m_findShellWatcher->result()); + restart(m_openParameters); + return; + } + + writeToTerminal( + ("\r\n\033[31m" + Tr::tr("Could not find shell to start.") + "\r\n").toUtf8(), true); + }); + + m_findShellWatcher->setFuture(Utils::asyncRun([shellCommand] { + const FilePath result = Utils::Terminal::defaultShellForDevice( + shellCommand.executable()); + if (result.isExecutableFile()) + return result; + return FilePath{}; + })); + + return; + } + Environment env = m_openParameters.environment.value_or(Environment{}) .appliedToEnvironment(shellCommand.executable().deviceEnvironment()); diff --git a/src/plugins/terminal/terminalwidget.h b/src/plugins/terminal/terminalwidget.h index dd20b3dfc0a..b696d8af1c0 100644 --- a/src/plugins/terminal/terminalwidget.h +++ b/src/plugins/terminal/terminalwidget.h @@ -16,6 +16,10 @@ #include #include +#include + +#include + namespace Terminal { using RegisteredAction = std::unique_ptr>; @@ -105,6 +109,8 @@ private: RegisteredAction m_close; Internal::ShortcutMap m_shortcutMap; + + std::unique_ptr> m_findShellWatcher; }; } // namespace Terminal