Файли
openidea/src/features/welcome/openRecent.test.ts
T
b0f65769c0 feat(remote): open WSL projects through a WSL transport (#989)
* 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]>
2026-11-05 15:37:19 +08:00

53 рядки
1.7 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const openProject = vi.fn();
const openRemoteProject = vi.fn();
const UNC = String.raw`\\wsl.localhost\Ubuntu\home\me\app`;
vi.mock("@/platform/ipc", async (orig) => {
const real = await orig<typeof import("@/platform/ipc")>();
return {
...real,
isTauri: () => true,
commands: {
...real.commands,
wslResolve: async (p: string) =>
p === UNC ? { target: { kind: "wsl", distro: "Ubuntu" }, path: "/home/me/app" } : null,
},
};
});
vi.mock("@/platform/project", async (orig) => {
const real = await orig<typeof import("@/platform/project")>();
return { ...real, openProject: (p: string) => openProject(p) };
});
vi.mock("@/workbench/projectWindow", () => ({
openRemoteProject: (...a: unknown[]) => openRemoteProject(...a),
}));
const { openRecent } = await import("./recent");
const { useProject } = await import("@/platform/project");
beforeEach(() => {
openProject.mockReset();
openRemoteProject.mockReset().mockResolvedValue(true);
useProject.setState({ project: null, lightEdit: false });
});
describe("openRecent", () => {
it("opens a legacy WSL UNC recent through the distro, not as a local folder", async () => {
expect(await openRecent({ path: UNC, name: "app" })).toBe(true);
expect(openRemoteProject).toHaveBeenCalledWith(
{ kind: "wsl", distro: "Ubuntu" },
"/home/me/app",
expect.any(Function),
);
expect(openProject).not.toHaveBeenCalled();
});
it("still opens a plain local recent locally", async () => {
await openRecent({ path: "/p/local", name: "local" });
expect(openProject).toHaveBeenCalledWith("/p/local");
expect(openRemoteProject).not.toHaveBeenCalled();
});
});