From c45197cc79e860dd647e04b6635172498569e2ad Mon Sep 17 00:00:00 2001 From: Dipesh Babu Date: Sat, 1 Aug 2026 10:37:34 -0400 Subject: [PATCH] Preserve whitespace in Git worktree paths --- sdk/typescript/src/targets.ts | 2 +- sdk/typescript/tests-ts/targets.test.ts | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sdk/typescript/src/targets.ts b/sdk/typescript/src/targets.ts index 0cd58206..8f6812d2 100644 --- a/sdk/typescript/src/targets.ts +++ b/sdk/typescript/src/targets.ts @@ -371,7 +371,7 @@ async function gitOutput( env: command.environment, }, ); - return stdout.trim(); + return stdout.replace(/\r?\n$/u, ""); } async function outermostGitMarkerRoot( diff --git a/sdk/typescript/tests-ts/targets.test.ts b/sdk/typescript/tests-ts/targets.test.ts index f8894cd8..c6218764 100644 --- a/sdk/typescript/tests-ts/targets.test.ts +++ b/sdk/typescript/tests-ts/targets.test.ts @@ -21,6 +21,7 @@ import { repositoryRevision, type ScanTarget, } from "../src/index.js"; +import { enclosingGitWorktreeRoot } from "../src/targets.js"; // @ts-expect-error DiffTarget is intentionally nominal; use its constructor helpers. const structurallyInvalidTarget: ScanTarget = { @@ -40,12 +41,12 @@ afterEach(async () => { ); }); -async function repository(): Promise { +async function repository(name = "repo"): Promise { const root = await realpath( await mkdtemp(join(tmpdir(), "codex-security-targets-")), ); temporaryDirectories.push(root); - const repo = join(root, "repo"); + const repo = join(root, name); await mkdir(join(repo, "src"), { recursive: true }); await writeFile(join(repo, "src", "app.ts"), "export const ok = true;\n"); git(repo, "init", "-b", "main"); @@ -123,6 +124,17 @@ describe("scan target normalization", () => { }); }); + test.skipIf(process.platform === "win32")( + "preserves trailing whitespace in Git worktree paths", + async () => { + const repo = await repository("repo "); + expect(await enclosingGitWorktreeRoot(repo)).toBe(await realpath(repo)); + await expect( + normalizeTarget(repo, DiffTarget.refs({ base: "HEAD" })), + ).resolves.toMatchObject({ kind: "refs" }); + }, + ); + test("rejects empty and escaping paths", async () => { const repo = await repository(); await expect(normalizeTarget(repo, [""])).rejects.toThrow("empty path");