diff --git a/src/resources/extensions/gsd/git-service.ts b/src/resources/extensions/gsd/git-service.ts index f96066d0d..36b018aa3 100644 --- a/src/resources/extensions/gsd/git-service.ts +++ b/src/resources/extensions/gsd/git-service.ts @@ -8,7 +8,7 @@ * paths, commit type inference, and the runGit shell helper. */ -import { execSync } from "node:child_process"; +import { execFileSync, execSync } from "node:child_process"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join, sep } from "node:path"; @@ -212,7 +212,7 @@ function filterGitSvnNoise(message: string): string { */ export function runGit(basePath: string, args: string[], options: { allowFailure?: boolean; input?: string } = {}): string { try { - return execSync(`git ${args.join(" ")}`, { + return execFileSync("git", args, { cwd: basePath, stdio: [options.input != null ? "pipe" : "ignore", "pipe", "pipe"], encoding: "utf-8", @@ -452,7 +452,7 @@ export class GitServiceImpl { } else { // Auto-detect: look for package.json with a test script try { - const pkg = execSync("cat package.json", { cwd: this.basePath, encoding: "utf-8" }); + const pkg = execFileSync("cat", ["package.json"], { cwd: this.basePath, encoding: "utf-8" }); const parsed = JSON.parse(pkg); if (parsed.scripts?.test) { command = "npm test"; diff --git a/src/resources/extensions/gsd/native-git-bridge.ts b/src/resources/extensions/gsd/native-git-bridge.ts index e613409a5..2e0e62d9b 100644 --- a/src/resources/extensions/gsd/native-git-bridge.ts +++ b/src/resources/extensions/gsd/native-git-bridge.ts @@ -5,7 +5,7 @@ // Only READ operations are native — WRITE operations (commit, merge, checkout, push) // remain as execSync calls in git-service.ts. -import { execSync } from "node:child_process"; +import { execFileSync } from "node:child_process"; /** Env overlay that suppresses interactive git credential prompts and git-svn noise. */ const GIT_NO_PROMPT_ENV = { @@ -44,10 +44,10 @@ function loadNative(): typeof nativeModule { return nativeModule; } -/** Run a git command via execSync. Returns trimmed stdout. */ +/** Run a git command via execFileSync. Returns trimmed stdout. */ function gitExec(basePath: string, args: string[], allowFailure = false): string { try { - return execSync(`git ${args.join(" ")}`, { + return execFileSync("git", args, { cwd: basePath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8", diff --git a/src/resources/extensions/gsd/worktree-manager.ts b/src/resources/extensions/gsd/worktree-manager.ts index 6696b7cf8..847dc4061 100644 --- a/src/resources/extensions/gsd/worktree-manager.ts +++ b/src/resources/extensions/gsd/worktree-manager.ts @@ -16,7 +16,7 @@ */ import { existsSync, mkdirSync, realpathSync } from "node:fs"; -import { execSync } from "node:child_process"; +import { execFileSync } from "node:child_process"; import { join, resolve, sep } from "node:path"; // ─── Types ───────────────────────────────────────────────────────────────── @@ -69,7 +69,7 @@ function filterGitSvnNoise(message: string): string { function runGit(cwd: string, args: string[], opts: { allowFailure?: boolean } = {}): string { try { - return execSync(`git ${args.join(" ")}`, { + return execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8",