diff --git a/bun.lock b/bun.lock index ecc84c85..15b89095 100644 --- a/bun.lock +++ b/bun.lock @@ -55,7 +55,7 @@ "react-dom": "^19.1.1", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1", - "simple-git": "^3.28.0", + "simple-git": "^3.36.0", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", "yaml": "^2.8.1", @@ -200,7 +200,7 @@ "remark-math": "^6.0.0", "remend": "^1.2.1", "shiki": "^3.23.0", - "simple-git": "^3.28.0", + "simple-git": "^3.36.0", "sonner": "^2.0.7", "strip-json-comments": "^5.0.3", "tailwind-merge": "^3.3.1", @@ -284,7 +284,7 @@ "qrcode-terminal": "^0.12.0", "reflect-metadata": "^0.2.2", "sherpa-onnx-node": "1.12.28", - "simple-git": "^3.28.0", + "simple-git": "^3.36.0", "web-push": "^3.6.7", "ws": "^8.18.3", "yaml": "^2.8.1", @@ -1258,6 +1258,10 @@ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + "@simple-git/args-pathspec": ["@simple-git/args-pathspec@1.0.3", "", {}, "sha512-ngJMaHlsWDTfjyq9F3VIQ8b7NXbBLq5j9i5bJ6XLYtD6qlDXT7fdKY2KscWWUF8t18xx052Y/PUO1K1TRc9yKA=="], + + "@simple-git/argv-parser": ["@simple-git/argv-parser@1.1.1", "", { "dependencies": { "@simple-git/args-pathspec": "^1.0.3" } }, "sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw=="], + "@simplewebauthn/browser": ["@simplewebauthn/browser@13.3.0", "", {}, "sha512-BE/UWv6FOToAdVk0EokzkqQQDOWtNydYlY6+OrmiZ5SCNmb41VehttboTetUM3T/fr6EAFYVXjz4My2wg230rQ=="], "@simplewebauthn/server": ["@simplewebauthn/server@13.3.1", "", { "dependencies": { "@hexagon/base64": "^1.1.27", "@levischuck/tiny-cbor": "^0.2.2", "@peculiar/asn1-android": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.1", "@peculiar/asn1-rsa": "^2.6.1", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "@peculiar/x509": "^1.14.3" } }, "sha512-GV/oM/qeycWn8p42JZIMJBsXWQcNFg+nJFzeQTnMA4gN8mXg0+HZFWJerHg8ZN/zlveMS3iV1wzuFpOVWS/46w=="], @@ -3000,7 +3004,7 @@ "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], - "simple-git": ["simple-git@3.32.3", "", { "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", "debug": "^4.4.0" } }, "sha512-56a5oxFdWlsGygOXHWrG+xjj5w9ZIt2uQbzqiIGdR/6i5iococ7WQ/bNPzWxCJdEUGUCmyMH0t9zMpRJTaKxmw=="], + "simple-git": ["simple-git@3.36.0", "", { "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", "@simple-git/args-pathspec": "^1.0.3", "@simple-git/argv-parser": "^1.1.0", "debug": "^4.4.0" } }, "sha512-cGQjLjK8bxJw4QuYT7gxHw3/IouVESbhahSsHrX97MzCL1gu2u7oy38W6L2ZIGECEfIBG4BabsWDPjBxJENv9Q=="], "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], diff --git a/package.json b/package.json index 20954910..3561555d 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "react-dom": "^19.1.1", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1", - "simple-git": "^3.28.0", + "simple-git": "^3.36.0", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", "yaml": "^2.8.1", diff --git a/packages/ui/package.json b/packages/ui/package.json index 060f392c..1bd40a73 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -77,7 +77,7 @@ "remark-math": "^6.0.0", "remend": "^1.2.1", "shiki": "^3.23.0", - "simple-git": "^3.28.0", + "simple-git": "^3.36.0", "sonner": "^2.0.7", "strip-json-comments": "^5.0.3", "tailwind-merge": "^3.3.1", diff --git a/packages/web/package.json b/packages/web/package.json index 7380dd7d..f5afcf43 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -42,7 +42,7 @@ "qrcode-terminal": "^0.12.0", "reflect-metadata": "^0.2.2", "sherpa-onnx-node": "1.12.28", - "simple-git": "^3.28.0", + "simple-git": "^3.36.0", "web-push": "^3.6.7", "ws": "^8.18.3", "yaml": "^2.8.1" diff --git a/packages/web/server/lib/git/service.js b/packages/web/server/lib/git/service.js index 4ece0521..ebe8c334 100644 --- a/packages/web/server/lib/git/service.js +++ b/packages/web/server/lib/git/service.js @@ -351,12 +351,17 @@ const buildGitEnv = async () => { return env; }; -const createGit = async (directory) => { +const createGit = async (directory, { allowUnsafeSshCommand = false } = {}) => { const env = await buildGitEnv(); const spawnOptions = { windowsHide: true }; const binary = getGitBinary(); const hasCustomBinary = typeof binary === 'string' && binary.trim() && binary !== 'git' && binary !== 'git.exe'; - const unsafe = hasCustomBinary ? { allowUnsafeCustomBinary: true } : undefined; + const unsafe = hasCustomBinary || allowUnsafeSshCommand + ? { + ...(hasCustomBinary && { allowUnsafeCustomBinary: true }), + ...(allowUnsafeSshCommand && { allowUnsafeSshCommand: true }), + } + : undefined; // Always pin simple-git to an explicit working directory. Omitting baseDir // makes simple-git use process.cwd(), which breaks when the OpenChamber // server was launched from a neutral directory (e.g. $HOME) and the opened @@ -2047,7 +2052,7 @@ export async function hasLocalIdentity(directory) { } export async function setLocalIdentity(directory, profile) { - const git = await createGit(directory); + const git = await createGit(directory, { allowUnsafeSshCommand: true }); try { @@ -2057,12 +2062,12 @@ export async function setLocalIdentity(directory, profile) { const authType = profile.authType || 'ssh'; if (authType === 'ssh' && profile.sshKey) { - await git.addConfig( + await git.raw([ + 'config', + '--local', 'core.sshCommand', - buildSshCommand(profile.sshKey), - false, - 'local' - ); + buildSshCommand(profile.sshKey) + ]); await git.raw(['config', '--local', '--unset', 'credential.helper']).catch(() => {}); } else if (authType === 'token' && profile.host) { await git.addConfig( diff --git a/packages/web/server/lib/git/service.test.js b/packages/web/server/lib/git/service.test.js index bf53b07f..e5110995 100644 --- a/packages/web/server/lib/git/service.test.js +++ b/packages/web/server/lib/git/service.test.js @@ -19,6 +19,7 @@ import { resetToCommit, resolveBaseRefForLog, revertCommit, + setLocalIdentity, stageFiles, unstageFiles, applyHunk, @@ -129,6 +130,23 @@ describe('git index path validation', () => { }); }); +describe.runIf(canRunGit())('setLocalIdentity', () => { + it('configures the local SSH command with the targeted simple-git opt-in', async () => { + const { tmpDir } = await createTempRepo(); + + await setLocalIdentity(tmpDir, { + userName: 'SSH User', + userEmail: 'ssh@example.com', + authType: 'ssh', + sshKey: '/tmp/test key', + }); + + expect(runGit(tmpDir, ['config', '--local', '--get', 'core.sshCommand']).trim()).toBe( + "ssh -i '/tmp/test key' -o IdentitiesOnly=yes" + ); + }); +}); + // --------------------------------------------------------------------------- // applyHunk (per-hunk stage / unstage / discard) // ---------------------------------------------------------------------------