дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-08 19:02:17 +02:00
Projects now open with a user-owned trust decision. The prompt offers Preview in Restricted Mode, Don't Open and Trust Project, with an optional trusted parent folder; preview is the default focus so Enter never grants trust. Restricted projects keep browsing, editing, saving, search and highlighting. Project-controlled execution is denied by default in the backend: run, debug, build, tools, language servers, plugins and Git commands that could honour repository configuration. Trusting a project enables those paths without reopening it, and decisions can be revoked in Settings. Terminals stay available when the user opens one, without project shell settings, environment or virtualenv activation. A shell prompt that runs git in the folder can still honour the repository's core.fsmonitor. Fixes #462
80 рядки
3.0 KiB
TypeScript
80 рядки
3.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { RemoteEntry } from "@/platform/ipc";
|
|
import {
|
|
initializeRemoteTrustMigration,
|
|
takeLegacyRemoteTrust,
|
|
forgetRemote,
|
|
parseRemoteLocation,
|
|
recentRemotes,
|
|
rememberRemote,
|
|
remoteLocation,
|
|
} from "@/platform/remote";
|
|
import { browsableFolders, listedDirectory, remoteParent } from "./model";
|
|
|
|
const entry = (path: string, isDir = true): RemoteEntry => ({
|
|
name: path.slice(path.lastIndexOf("/") + 1),
|
|
path,
|
|
isDir,
|
|
isSymlink: false,
|
|
size: 0,
|
|
mtime: null,
|
|
permissions: "rwxr-xr-x",
|
|
});
|
|
|
|
describe("remote folder browser", () => {
|
|
it("goes up one level and stops at the root", () => {
|
|
expect(remoteParent("/home/dev/app")).toBe("/home/dev");
|
|
expect(remoteParent("/home/dev/")).toBe("/home");
|
|
expect(remoteParent("/home")).toBe("/");
|
|
expect(remoteParent("/")).toBe("/");
|
|
});
|
|
|
|
it("lists folders only, hidden ones last", () => {
|
|
const names = browsableFolders([
|
|
entry("/h/.cache"),
|
|
entry("/h/zeta"),
|
|
entry("/h/notes.txt", false),
|
|
entry("/h/alpha"),
|
|
]).map((e) => e.name);
|
|
expect(names).toEqual(["alpha", "zeta", ".cache"]);
|
|
});
|
|
|
|
it("resolves `~` from the listing", () => {
|
|
expect(listedDirectory("~", [entry("/home/dev/app")])).toBe("/home/dev");
|
|
expect(listedDirectory("~", [])).toBe("~");
|
|
expect(listedDirectory("/srv/", [])).toBe("/srv");
|
|
expect(listedDirectory("/", [])).toBe("/");
|
|
});
|
|
});
|
|
|
|
describe("remote project locations", () => {
|
|
it("round-trip the configuration id and the path", () => {
|
|
const loc = remoteLocation("mac mini/1", "/Users/me/repo");
|
|
expect(loc).toBe("ssh://mac%20mini%2F1/Users/me/repo");
|
|
expect(parseRemoteLocation(loc)).toEqual({ sshConfig: "mac mini/1", path: "/Users/me/repo" });
|
|
expect(parseRemoteLocation("/Users/me/repo")).toBeNull();
|
|
});
|
|
|
|
it("remembers recent remote projects most recent first, once each", () => {
|
|
localStorage.clear();
|
|
rememberRemote({ sshConfig: "a", path: "/p", name: "p", host: "me@a", openedAtMs: 1 });
|
|
rememberRemote({ sshConfig: "b", path: "/q", name: "q", host: "me@b", openedAtMs: 2 });
|
|
rememberRemote({ sshConfig: "a", path: "/p", name: "p", host: "me@a", openedAtMs: 3 });
|
|
expect(recentRemotes().map((r) => r.path)).toEqual(["/p", "/q"]);
|
|
forgetRemote("a", "/p");
|
|
expect(recentRemotes().map((r) => r.path)).toEqual(["/q"]);
|
|
});
|
|
});
|
|
|
|
it("migrates only the original remote recents once, scoped to the saved host", () => {
|
|
localStorage.clear();
|
|
rememberRemote({ sshConfig: "a", path: "/old", host: "me@old", name: "old", openedAtMs: 1 });
|
|
initializeRemoteTrustMigration();
|
|
rememberRemote({ sshConfig: "a", path: "/new", host: "me@old", name: "new", openedAtMs: 2 });
|
|
initializeRemoteTrustMigration();
|
|
expect(takeLegacyRemoteTrust("a", "/new", "me@old")).toBe(false);
|
|
expect(takeLegacyRemoteTrust("a", "/old", "me@other")).toBe(false);
|
|
expect(takeLegacyRemoteTrust("a", "/old", "me@old")).toBe(true);
|
|
expect(takeLegacyRemoteTrust("a", "/old", "me@old")).toBe(false);
|
|
});
|