дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 03:05:40 +02:00
* perf(vfs): list directories off the main thread and reuse the repository lookup Opening a folder on a network share (\\wsl.localhost\<distro>\...) is slow because every listing ran on the main thread and walked up to the repository root and ran a repository discovery again. - fs_read_dir runs on the blocking pool. - GitignoreStack::cached keeps the repository root and the repo-level rules for a few seconds. An edit of .git/info/exclude is still seen at once (its mtime and size are checked) and every .gitignore / .ignore is read fresh. Refs #916 * feat(remote): open WSL projects through a WSL transport A folder of a WSL distro (\\wsl.localhost\<distro>\... or \\wsl$\...) now opens as a remote project whose openidea-server runs inside the distro, so the terminal, SDK discovery, run, language servers and git are native Linux. - RemoteTarget (ssh | wsl) replaces the SSH configuration id in the remote launch, connection, session and recents; old recents are read as SSH and a WSL target never inherits the legacy trust migration. - remote_wsl: probe the distro, stream the server into ~/.openidea/server and start it with `wsl.exe -d <distro> --exec <bin> --stdio`. Distro names are validated and every command goes through --exec with positional arguments. - wsl_distros / wsl_resolve commands; File > Open, the CLI and recents route WSL folders to the distro and focus the window that already has them. - Remote Development dialog: SSH/WSL choice with the detected distros; the status bar shows `WSL: <distro>` / `SSH: <host>`. - ide-jsonrpc: skip the NUL left at the start of a line by UTF-16 output of wsl.exe, which made the first message of the server disappear. Not run on Windows yet: only a stand-in for wsl.exe is tested. Refs #925, #327, #721 * fix(remote): satisfy clippy in WSL output decoding * style(run): format run types * fix: regenerate bindings and drop untranslated WSL catalog entry * test(i18n): list WSL as an untranslated product name * fix(run): pick build wrappers and shell quoting by the execution host A remote window runs commands on its Linux or macOS server, so a Windows desktop no longer selects gradlew.bat, mvnw.cmd or Windows quoting for it. * fix(welcome): open legacy WSL UNC recents and sessions through the distro Recents and the restored session called the local openProject for a \\wsl.localhost folder saved before WSL projects, which fails with OS error 123. They now resolve it like the other entry points. * fix(windows): keep WSL files out of remote project launches path_launch tested the WSL share before is_dir, so a first-instance CLI launch with a WSL file opened a remote project instead of LightEdit. * fix(remote): run-command OS comes from the remote host, not an assumption The server's OS was dropped after connect, so a restored session had none and isWindows() assumed every remote host is Unix. Keep it on the connection and the session, and resolve it through hostOs(). --------- Co-authored-by: NguyenBang <[email protected]> Co-authored-by: NguyenBang <[email protected]> Co-authored-by: l0ng-ai <[email protected]>
100 рядки
3.3 KiB
TypeScript
100 рядки
3.3 KiB
TypeScript
/**
|
|
* Remote development: a window whose project lives on an SSH host or in a WSL distribution. The backend
|
|
* (`openidea-server`) runs there and this window routes its commands to it
|
|
* (platform/remote.ts).
|
|
*/
|
|
import { registerActions } from "@/platform/actions";
|
|
import { disconnectRemote, useRemote } from "@/platform/remote";
|
|
import { lazyComponent } from "@/ui";
|
|
import { maybeEditorService, registerOverlay, registerStatusItem, registerToolWindow } from "@/workbench/contributions";
|
|
import { confirmLeaveProject } from "@/platform/project";
|
|
import { ConnectHost } from "./ConnectDialog";
|
|
import { reloadEnvironment } from "./environment";
|
|
import { RemoteStatus } from "./RemoteStatus";
|
|
import { closeConnectDialog, openConnectDialog } from "./model";
|
|
import { restorePorts, usePorts } from "./ports";
|
|
|
|
/** SSH tunnels are available while this window is connected to an SSH host. */
|
|
function trackPortsWindow(): () => void {
|
|
let off: (() => void) | null = null;
|
|
const sync = (connected: boolean) => {
|
|
if (connected && !off) {
|
|
void restorePorts();
|
|
off = registerToolWindow({
|
|
id: "remote.ports",
|
|
title: "Ports",
|
|
icon: "web",
|
|
anchor: "bottom",
|
|
order: 40,
|
|
stripe: "onUse",
|
|
component: lazyComponent(() => import("./PortsView").then((m) => m.PortsView)),
|
|
});
|
|
} else if (!connected && off) {
|
|
off();
|
|
off = null;
|
|
usePorts.setState({ ports: [] });
|
|
}
|
|
};
|
|
sync(useRemote.getState().session?.target.kind === "ssh");
|
|
const unsubscribe = useRemote.subscribe((s) => sync(s.session?.target.kind === "ssh"));
|
|
return () => {
|
|
unsubscribe();
|
|
off?.();
|
|
};
|
|
}
|
|
|
|
export function activate(): () => void {
|
|
const disposers = [
|
|
trackPortsWindow(),
|
|
registerOverlay({ id: "remote.connect", component: ConnectHost }),
|
|
registerStatusItem({
|
|
id: "remote.location",
|
|
title: "Remote Host",
|
|
align: "left",
|
|
priority: 100,
|
|
component: RemoteStatus,
|
|
}),
|
|
registerActions([
|
|
{
|
|
id: "remote.connect",
|
|
title: "Remote Development…",
|
|
description: "Opens a project folder on an SSH host; the IDE backend runs on that host.",
|
|
category: "File",
|
|
icon: "folder",
|
|
keywords: ["ssh", "remote", "server", "gateway", "connect", "host"],
|
|
run: () => openConnectDialog(),
|
|
},
|
|
{
|
|
id: "remote.disconnect",
|
|
title: "Disconnect from Remote Host",
|
|
category: "File",
|
|
keywords: ["ssh", "remote", "close"],
|
|
when: "projectOpen",
|
|
run: async () => {
|
|
if (!(await confirmLeaveProject())) return;
|
|
try {
|
|
await disconnectRemote();
|
|
} catch (e) {
|
|
maybeEditorService()?.cancelClose?.();
|
|
throw e;
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "remote.reloadEnvironment",
|
|
title: "Reload Environment",
|
|
description:
|
|
"Reads the login shell's environment (and devcontainer.json remoteEnv on a remote host) again for new terminals and processes.",
|
|
category: "File",
|
|
keywords: ["env", "environment", "variables", "path", "shell", "remoteEnv", "devcontainer", "reload"],
|
|
when: "projectOpen",
|
|
run: () => reloadEnvironment(),
|
|
},
|
|
]),
|
|
];
|
|
return () => {
|
|
disposers.reverse().forEach((d) => d());
|
|
closeConnectDialog();
|
|
};
|
|
}
|