authorgravatar for lucenz@proton.meSimone <lucenz@proton.me> 2026-08-14 23:56:12+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-14 17:56:12-04:00
logf0719072a1c6435b5a91243afc57bc8bf1f3e2b6
tree30f8fb5ffbfa4d31e8a5c7118738d70fa41c819a
parent9885a845c97325b1099b095011da8385485616f5
signature Signed by PGP key B5690EEEBB952194

fix(server): handle files named HEAD in git status (#6397)

Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>

2 files changed, 26 insertions(+), 4 deletions(-)

apps/server/src/vcs/GitVcsDriverCore.test.ts+21
......@@ -950,6 +950,27 @@ it.layer(TestLayer)("GitVcsDriver core integration", (it) => {
950950 }),
951951 );
952952
953 it.effect("reports changes to a file named HEAD", () =>
954 Effect.gen(function* () {
955 const cwd = yield* makeTmpDir();
956 yield* initRepoWithCommit(cwd);
957 yield* writeTextFile(cwd, "HEAD", "first line\n");
958 yield* git(cwd, ["add", "HEAD"]);
959 yield* git(cwd, ["commit", "-m", "add HEAD file"]);
960 yield* writeTextFile(cwd, "HEAD", "first line\nsecond line\n");
961
962 const status = yield* (yield* GitVcsDriver.GitVcsDriver).statusDetails(cwd);
963
964 assert.equal(status.isRepo, true);
965 assert.equal(status.hasWorkingTreeChanges, true);
966 assert.deepInclude(status.workingTree.files, {
967 path: "HEAD",
968 insertions: 1,
969 deletions: 0,
970 });
971 }),
972 );
973
953974 it.effect("reports default-branch delta separately from upstream delta", () =>
954975 Effect.gen(function* () {
955976 const cwd = yield* makeTmpDir();
apps/server/src/vcs/GitVcsDriverCore.ts+5-4
......@@ -420,9 +420,10 @@ function isNonRepositoryGitStderr(stderr: string): boolean {
420420 return stderr.toLowerCase().includes("not a git repository");
421421}
422422function isUnbornHeadStderr(stderr: string): boolean {
423 const normalized = stderr.toLowerCase();
423424 return (
424 stderr.toLowerCase().includes("unknown revision") &&
425 stderr.toLowerCase().includes("path not in the working tree")
425 normalized.includes("bad revision 'head'") ||
426 (normalized.includes("unknown revision") && normalized.includes("path not in the working tree"))
426427 );
427428}
428429
......@@ -1600,7 +1601,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
16001601 executeGitWithStableDiagnostics(
16011602 "GitVcsDriver.statusDetails.numstat",
16021603 cwd,
1603 ["diff", "HEAD", "--numstat"],
1604 ["diff", "HEAD", "--numstat", "--"],
16041605 { allowNonZeroExit: true },
16051606 ).pipe(
16061607 Effect.flatMap((result) => {
......@@ -1642,7 +1643,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
16421643 ...gitCommandContext({
16431644 operation: "GitVcsDriver.statusDetails.numstat",
16441645 cwd,
1645 args: ["diff", "HEAD", "--numstat"],
1646 args: ["diff", "HEAD", "--numstat", "--"],
16461647 }),
16471648 detail: "git diff HEAD --numstat failed.",
16481649 exitCode: result.exitCode,