дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 03:05:40 +02:00
feat(remote): reopen a local project in its dev container (#1843)
Refs #1083 (step B). A local project with a devcontainer.json can be reopened in its dev container (File › Reopen in Container, Find Action): the Dev Containers CLI brings the container up and the window connects to openidea-server inside it, as for WSL, so terminal, language servers, run, debug and git work in the container. The project's identity stays the local folder, so reopening from Recent Projects finds the same container. Missing CLI gives install guidance; trust of the local project carries over. Pure CLI output parsing lives in ide-remote; a failed connection no longer closes the current backend early, saved locations keep the container configuration, and Docker context precedence follows the CLI. Co-authored-by: andreabasile <[email protected]>
Цей коміт міститься в:
1 джерело
7479b7ad9d
коміт
60d7dcdca0
29 files changed
+908
-69
No files matched your search
@@ -172,6 +172,7 @@
|
||||
"menu.file.newProjectsSettings": "Settings for New Projects…",
|
||||
"menu.file.toggleReadOnly": "Make File Read-only / Writable",
|
||||
"menu.file.closeProject": "Close Project",
|
||||
"menu.remote.reopenInContainer": "Reopen in Container",
|
||||
"menu.remote.reloadEnvironment": "Reload Environment",
|
||||
"menu.file.new": "New…",
|
||||
"menu.file.newScratchFile": "New Scratch File…",
|
||||
|
||||
@@ -201,5 +201,12 @@
|
||||
"Only Python can be debugged in containers": "Only Python can be debugged in containers",
|
||||
"Docker connections come from the Services tool window. Each run gets a new container, removed when it ends. Python configurations can be debugged there; coverage and profiling stay on this machine.": "Docker connections come from the Services tool window. Each run gets a new container, removed when it ends. Python configurations can be debugged there; coverage and profiling stay on this machine.",
|
||||
"Use Project JDK": "Use Project JDK",
|
||||
"JDK used for Maven sync, builds, goals and tests. An explicit JAVA_HOME in a run configuration takes precedence.": "JDK used for Maven sync, builds, goals and tests. An explicit JAVA_HOME in a run configuration takes precedence."
|
||||
"JDK used for Maven sync, builds, goals and tests. An explicit JAVA_HOME in a run configuration takes precedence.": "JDK used for Maven sync, builds, goals and tests. An explicit JAVA_HOME in a run configuration takes precedence.",
|
||||
"Starting the dev container…": "Starting the dev container…",
|
||||
"Command-line tool": "Command-line tool",
|
||||
"Forwarding ports is not supported in a dev container yet": "Forwarding ports is not supported in a dev container yet",
|
||||
"Could not reopen the project in a container": "Could not reopen the project in a container",
|
||||
"Reopen in Container": "Reopen in Container",
|
||||
"Builds or starts the project's dev container (devcontainer.json) with the Dev Containers CLI and opens the project in it.": "Builds or starts the project's dev container (devcontainer.json) with the Dev Containers CLI and opens the project in it.",
|
||||
"devcontainer up exited with {status}": "devcontainer up exited with {status}"
|
||||
}
|
||||
@@ -6541,6 +6541,12 @@
|
||||
"Where updates are downloaded from. If it can't be reached, the other source is tried.": "从哪里下载更新。无法连接时会改用另一个源。",
|
||||
"CNB (China mirror)": "CNB(国内镜像)",
|
||||
"Remote connection cancelled": "远程连接已取消",
|
||||
"Starting the dev container…": "正在启动开发容器…",
|
||||
"Command-line tool": "命令行工具",
|
||||
"Forwarding ports is not supported in a dev container yet": "开发容器暂不支持端口转发",
|
||||
"Could not reopen the project in a container": "无法在容器中重新打开项目",
|
||||
"Reopen in Container": "在容器中重新打开",
|
||||
"Builds or starts the project's dev container (devcontainer.json) with the Dev Containers CLI and opens the project in it.": "使用 Dev Containers CLI 构建或启动项目的开发容器(devcontainer.json),并在其中打开项目。",
|
||||
"Xdebug is not loaded in PHP {version}": "PHP {version} 未加载 Xdebug",
|
||||
"{php} runs without Xdebug, so breakpoints are skipped. Install Xdebug 3 for this PHP or choose another PHP interpreter.": "{php} 运行时没有 Xdebug,断点会被跳过。请为此 PHP 安装 Xdebug 3,或选择其他 PHP 解释器。",
|
||||
"Open PHP Settings": "打开 PHP 设置",
|
||||
@@ -6579,5 +6585,6 @@
|
||||
"The container exited before debugpy was ready. Check the Run console for errors.": "容器在 debugpy 就绪前已退出。请检查运行控制台中的错误。",
|
||||
"debugpy did not become ready within 120 seconds. Check the Run console and the container's Python interpreter.": "debugpy 未在 120 秒内就绪。请检查运行控制台和容器的 Python 解释器。",
|
||||
"Use Project JDK": "使用项目 SDK",
|
||||
"JDK used for Maven sync, builds, goals and tests. An explicit JAVA_HOME in a run configuration takes precedence.": "用于 Maven 同步、构建、目标和测试的 JDK。运行配置中显式设置的 JAVA_HOME 优先。"
|
||||
"JDK used for Maven sync, builds, goals and tests. An explicit JAVA_HOME in a run configuration takes precedence.": "用于 Maven 同步、构建、目标和测试的 JDK。运行配置中显式设置的 JAVA_HOME 优先。",
|
||||
"devcontainer up exited with {status}": "devcontainer up 已退出,状态为 {status}"
|
||||
}
|
||||
@@ -172,6 +172,7 @@
|
||||
"menu.file.newProjectsSettings": "新项目的设置…",
|
||||
"menu.file.toggleReadOnly": "将文件设为只读/可写",
|
||||
"menu.file.closeProject": "关闭项目",
|
||||
"menu.remote.reopenInContainer": "在容器中重新打开",
|
||||
"menu.remote.reloadEnvironment": "重新加载环境",
|
||||
"menu.file.new": "新建…",
|
||||
"menu.file.newScratchFile": "新建临时文件…",
|
||||
|
||||
@@ -154,7 +154,10 @@ export const useRemoteProgress = create<{ progress: RemoteProgress | null; locat
|
||||
location: null,
|
||||
}));
|
||||
|
||||
/** Opens `path` of `target` (an SSH host or a WSL distribution) in this window. */
|
||||
/**
|
||||
* Opens `path` of `target` (an SSH host or a WSL distribution) in this window. A dev container's
|
||||
* project folder is the one in the container: `path` is then only a label.
|
||||
*/
|
||||
export async function connectRemote(target: RemoteTarget, path: string) {
|
||||
useProject.setState({ opening: true });
|
||||
const location = remoteLocation(target, path);
|
||||
@@ -214,23 +217,35 @@ export async function disconnectRemote() {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Remote project locations: `ssh://<configuration id>/<absolute path>` or
|
||||
// `wsl://<distribution>/<absolute path>`, what the session and the recent projects
|
||||
// remember for a remote window.
|
||||
// Remote project locations: `ssh://<configuration id>/<absolute path>`,
|
||||
// `wsl://<distribution>/<absolute path>` or `devcontainer://<local folder>[:<config>]/<container path>`,
|
||||
// what the session and the recent projects remember for a remote window.
|
||||
|
||||
const SCHEMES = { ssh: "ssh://", wsl: "wsl://" } as const;
|
||||
const SCHEMES = { ssh: "ssh://", wsl: "wsl://", devContainer: "devcontainer://" } as const;
|
||||
|
||||
/** The SSH configuration id or the WSL distribution name. */
|
||||
/** The SSH configuration id, the WSL distribution name or the dev container's local folder. */
|
||||
export function targetName(target: RemoteTarget): string {
|
||||
return target.kind === "ssh" ? target.config : target.distro;
|
||||
switch (target.kind) {
|
||||
case "ssh":
|
||||
return target.config;
|
||||
case "wsl":
|
||||
return target.distro;
|
||||
case "devContainer":
|
||||
return target.folder;
|
||||
}
|
||||
}
|
||||
|
||||
export function sameTarget(a: RemoteTarget, b: RemoteTarget): boolean {
|
||||
return a.kind === b.kind && targetName(a) === targetName(b);
|
||||
return (
|
||||
a.kind === b.kind &&
|
||||
targetName(a) === targetName(b) &&
|
||||
(a.kind !== "devContainer" || b.kind !== "devContainer" || a.config === b.config)
|
||||
);
|
||||
}
|
||||
|
||||
export function remoteLocation(target: RemoteTarget, path: string): string {
|
||||
return `${SCHEMES[target.kind]}${encodeURIComponent(targetName(target))}${path.startsWith("/") ? "" : "/"}${path}`;
|
||||
const config = target.kind === "devContainer" && target.config ? `:${encodeURIComponent(target.config)}` : "";
|
||||
return `${SCHEMES[target.kind]}${encodeURIComponent(targetName(target))}${config}${path.startsWith("/") ? "" : "/"}${path}`;
|
||||
}
|
||||
|
||||
export function parseRemoteLocation(location: string): { target: RemoteTarget; path: string } | null {
|
||||
@@ -239,8 +254,12 @@ export function parseRemoteLocation(location: string): { target: RemoteTarget; p
|
||||
const rest = location.slice(SCHEMES[kind].length);
|
||||
const slash = rest.indexOf("/");
|
||||
if (slash <= 0) return null;
|
||||
const name = decodeURIComponent(rest.slice(0, slash));
|
||||
const target: RemoteTarget = kind === "ssh" ? { kind, config: name } : { kind, distro: name };
|
||||
const authority = rest.slice(0, slash);
|
||||
const colon = kind === "devContainer" ? authority.indexOf(":") : -1;
|
||||
const name = decodeURIComponent(colon < 0 ? authority : authority.slice(0, colon));
|
||||
const config = colon < 0 ? "" : decodeURIComponent(authority.slice(colon + 1));
|
||||
const target: RemoteTarget =
|
||||
kind === "ssh" ? { kind, config: name } : kind === "wsl" ? { kind, distro: name } : { kind, folder: name, config };
|
||||
return { target, path: rest.slice(slash) };
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Заблокувати користувача