From cdfbeee2e410b026a279b445e2fd69811fd4edc9 Mon Sep 17 00:00:00 2001 From: Simone <185146821+Lucenx9@users.noreply.github.com> Date: Thu, 13 Aug 2026 01:27:17 +0200 Subject: [PATCH] fix(server): handle files named HEAD in git status --- apps/server/src/vcs/GitVcsDriverCore.test.ts | 21 ++++++++++++++++++++ apps/server/src/vcs/GitVcsDriverCore.ts | 9 +++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/apps/server/src/vcs/GitVcsDriverCore.test.ts b/apps/server/src/vcs/GitVcsDriverCore.test.ts index 18e594512ee..fc1b4d127bf 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.test.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.test.ts @@ -950,6 +950,27 @@ it.layer(TestLayer)("GitVcsDriver core integration", (it) => { }), ); + it.effect("reports changes to a file named HEAD", () => + Effect.gen(function* () { + const cwd = yield* makeTmpDir(); + yield* initRepoWithCommit(cwd); + yield* writeTextFile(cwd, "HEAD", "first line\n"); + yield* git(cwd, ["add", "HEAD"]); + yield* git(cwd, ["commit", "-m", "add HEAD file"]); + yield* writeTextFile(cwd, "HEAD", "first line\nsecond line\n"); + + const status = yield* (yield* GitVcsDriver.GitVcsDriver).statusDetails(cwd); + + assert.equal(status.isRepo, true); + assert.equal(status.hasWorkingTreeChanges, true); + assert.deepInclude(status.workingTree.files, { + path: "HEAD", + insertions: 1, + deletions: 0, + }); + }), + ); + it.effect("reports default-branch delta separately from upstream delta", () => Effect.gen(function* () { const cwd = yield* makeTmpDir(); diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index 1489db9b3ff..9162865370b 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -420,9 +420,10 @@ function isNonRepositoryGitStderr(stderr: string): boolean { return stderr.toLowerCase().includes("not a git repository"); } function isUnbornHeadStderr(stderr: string): boolean { + const normalized = stderr.toLowerCase(); return ( - stderr.toLowerCase().includes("unknown revision") && - stderr.toLowerCase().includes("path not in the working tree") + normalized.includes("bad revision 'head'") || + (normalized.includes("unknown revision") && normalized.includes("path not in the working tree")) ); } @@ -1600,7 +1601,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* executeGitWithStableDiagnostics( "GitVcsDriver.statusDetails.numstat", cwd, - ["diff", "HEAD", "--numstat"], + ["diff", "HEAD", "--numstat", "--"], { allowNonZeroExit: true }, ).pipe( Effect.flatMap((result) => { @@ -1642,7 +1643,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* ...gitCommandContext({ operation: "GitVcsDriver.statusDetails.numstat", cwd, - args: ["diff", "HEAD", "--numstat"], + args: ["diff", "HEAD", "--numstat", "--"], }), detail: "git diff HEAD --numstat failed.", exitCode: result.exitCode,