Always create a fresh worktree (#3224)

* fix(server): always create requested worktrees

A slug is a preferred name, not workspace identity. Let the worktree creator suffix occupied paths and branches so duplicate and detached-slug requests still create fresh worktrees.

* fix(server): suffix occupied checkout branches

Fresh creation also applies when checkout targets are already in use. Create a suffixed branch from the requested branch instead of rejecting the request.

* test(server): align occupied branch coverage

* test(server): remove stale worktree reuse expectations
This commit is contained in:
Mohamed Boudra
2026-08-11 17:54:59 +02:00
committed by GitHub
parent 308e9af845
commit b2ff359b60
7 changed files with 175 additions and 95 deletions
@@ -2,7 +2,6 @@
/* eslint-disable max-nested-callbacks */
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import {
BranchAlreadyCheckedOutError,
createWorktree as createWorktreePrimitive,
deriveWorktreeProjectHash,
deletePaseoWorktree,
@@ -299,22 +298,17 @@ describe.skipIf(isPlatform("win32"))("worktree POSIX-only", () => {
expect(currentBranch).toBe("release/1.1.15");
});
it("throws a typed error when checking out a branch already checked out in the main repo", async () => {
let caughtError: unknown;
try {
await createLegacyWorktreeForTest({
cwd: repoDir,
worktreeSlug: "dev-worktree",
source: { kind: "checkout-branch", branchName: "main" },
runSetup: true,
paseoHome,
});
} catch (error) {
caughtError = error;
}
it("creates a suffixed branch when checking out a branch already checked out in the main repo", async () => {
const result = await createLegacyWorktreeForTest({
cwd: repoDir,
worktreeSlug: "dev-worktree",
source: { kind: "checkout-branch", branchName: "main" },
runSetup: true,
paseoHome,
});
expect(caughtError).toBeInstanceOf(BranchAlreadyCheckedOutError);
expect((caughtError as BranchAlreadyCheckedOutError).branchName).toBe("main");
expect(result.branchName).toBe("main-1");
expect(existsSync(result.worktreePath)).toBe(true);
});
it("fetches a GitHub PR branch, checks it out, writes metadata, and runs setup", async () => {