From 7e43d90aa51b90daa9b36f9882fdbd80c1984463 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Wed, 29 Jul 2026 10:45:23 +0000 Subject: [PATCH] fix(projects): retain absolute scp users --- packages/server/src/server/project-key.test.ts | 15 +++++++++++++++ packages/server/src/server/project-key.ts | 10 ++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/server/src/server/project-key.test.ts b/packages/server/src/server/project-key.test.ts index e548a35a9..84717ac6f 100644 --- a/packages/server/src/server/project-key.test.ts +++ b/packages/server/src/server/project-key.test.ts @@ -189,6 +189,21 @@ describe("deriveProjectKey", () => { ); }); + test("distinguishes SSH users for absolute SCP paths", () => { + const rootPath = path.resolve("repo"); + const derive = (remoteUrl: string) => + deriveProjectKey({ + rootPath, + remoteUrl, + worktreeRoot: rootPath, + mainRepoRoot: null, + }); + + expect(derive("alice@git.example.com:/srv/repo.git")).not.toBe( + derive("bob@git.example.com:/srv/repo.git"), + ); + }); + test("distinguishes SSH users for generic URL remotes", () => { const rootPath = path.resolve("repo"); const derive = (remoteUrl: string) => diff --git a/packages/server/src/server/project-key.ts b/packages/server/src/server/project-key.ts index 88799d47f..bd04c5c68 100644 --- a/packages/server/src/server/project-key.ts +++ b/packages/server/src/server/project-key.ts @@ -70,9 +70,7 @@ function deriveRemoteProjectKey(remoteUrl: string | null): string | null { remote.stripDotGitSuffix, ); if (!cleanedPath) return null; - const userPrefix = remote.relativePathUser - ? `${encodeURIComponent(remote.relativePathUser)}@` - : ""; + const userPrefix = remote.user ? `${encodeURIComponent(remote.user)}@` : ""; const normalizedHost = remote.host.toLowerCase(); const normalizedPath = normalizedHost === "github.com" ? cleanedPath.toLowerCase() : cleanedPath; const transportPrefix = remote.transport ? `${remote.transport}//` : ""; @@ -83,7 +81,7 @@ interface RemoteLocation { host: string; path: string; transport: string | null; - relativePathUser: string | null; + user: string | null; preserveLeadingSlash: boolean; decodePercentEncoding: boolean; stripDotGitSuffix: boolean; @@ -107,7 +105,7 @@ function parseScpRemote(remoteUrl: string): RemoteLocation | null { host: normalizedHost, path: remotePath, transport: null, - relativePathUser: user && user !== "git" && !preserveLeadingSlash ? user : null, + user: user && user !== "git" ? user : null, preserveLeadingSlash, decodePercentEncoding: false, stripDotGitSuffix: CLOUD_FORGE_HOSTS.has(host.toLowerCase()), @@ -130,7 +128,7 @@ function parseUrlRemote(remoteUrl: string): RemoteLocation | null { host, path: remotePath, transport: forgeHost || isSsh ? null : parsed.protocol.toLowerCase(), - relativePathUser: + user: isSsh && !forgeHost && parsed.username && parsed.username !== "git" ? decodeUrlComponent(parsed.username) : null,