fix(workspace): skip git init for workspace-mode project roots
ensureGitRepositoryForProjectPath unconditionally ran `git init` on non-git paths, including workspace roots. This created a stray empty repo with unborn HEAD at the workspace root, poisoning every downstream git command (executor session cwd: `fatal: ambiguous argument 'HEAD'`). Add an early-return guard that checks loadWorkspaceConfig before any git operation, keeping the workspace root non-git as intended by the workspace execution contract.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { execFile } from "node:child_process";
|
||||
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
@@ -107,4 +107,17 @@ describe("ensureGitRepositoryForProjectPath", () => {
|
||||
ensureGitRepositoryForProjectPath(projectPath, { runner }),
|
||||
).rejects.toBeInstanceOf(GitRepositoryInitializationError);
|
||||
});
|
||||
|
||||
it("skips git init for a workspace-mode project root (.fusion/workspace.json present)", async () => {
|
||||
const projectPath = tempDir("fusion-git-workspace-");
|
||||
// Simulate workspace init: .fusion/workspace.json exists, root is non-git
|
||||
mkdirSync(join(projectPath, ".fusion"), { recursive: true });
|
||||
writeFileSync(join(projectPath, ".fusion", "workspace.json"), JSON.stringify({ repos: ["repo-a"] }));
|
||||
|
||||
const outcome = await ensureGitRepositoryForProjectPath(projectPath);
|
||||
|
||||
expect(outcome).toBe("existing");
|
||||
// No .git should be created at the workspace root
|
||||
expect(existsSync(join(projectPath, ".git"))).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -41,6 +41,20 @@ export async function ensureGitRepositoryForProjectPath(
|
||||
const runner = options.runner ?? runGitCommand;
|
||||
const timeout = options.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
|
||||
|
||||
/*
|
||||
FNXC:Workspace 2026-06-24-10:00:
|
||||
A workspace-mode project root is intentionally NOT a git repository — it is a parent
|
||||
directory containing multiple git sub-repos (detected at init time and recorded in
|
||||
.fusion/workspace.json). Running `git init` here would create a stray empty repo at the
|
||||
workspace root, poisoning every downstream git command: the executor sets the session cwd
|
||||
to this root (browse-only), and `git rev-parse --abbrev-ref HEAD` fails on the unborn HEAD
|
||||
with "ambiguous argument 'HEAD'". Detect workspace mode via the config file and skip the
|
||||
git-init so the root stays non-git, matching the workspace execution contract (KTD1).
|
||||
*/
|
||||
if (await loadWorkspaceConfig(projectPath)) {
|
||||
return "existing";
|
||||
}
|
||||
|
||||
if (await isInsideGitWorkTree(projectPath, runner, timeout)) {
|
||||
return "existing";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user