(params: {
projectPath: string;
branchName: string;
directoryName?: string;
trunkBranch: string;
startPoint?: string;
skipRemoteSync?: boolean;
workspacePathOverride?: string;
initLogger: InitLogger;
abortSignal?: AbortSignal;
env?: Record<string, string>;
trusted?: boolean;
})
| 67 | } |
| 68 | |
| 69 | async createWorkspace(params: { |
| 70 | projectPath: string; |
| 71 | branchName: string; |
| 72 | directoryName?: string; |
| 73 | trunkBranch: string; |
| 74 | startPoint?: string; |
| 75 | skipRemoteSync?: boolean; |
| 76 | workspacePathOverride?: string; |
| 77 | initLogger: InitLogger; |
| 78 | abortSignal?: AbortSignal; |
| 79 | env?: Record<string, string>; |
| 80 | trusted?: boolean; |
| 81 | }): Promise<WorkspaceCreationResult> { |
| 82 | const { projectPath, branchName, trunkBranch, initLogger } = params; |
| 83 | // Disable git hooks for untrusted projects (prevents post-checkout execution) |
| 84 | const noHooksEnv = this.getGitExecOptions(params.trusted, params.abortSignal); |
| 85 | const workspaceName = params.directoryName ?? branchName; |
| 86 | const workspacePath = |
| 87 | params.workspacePathOverride ?? this.getWorkspacePath(projectPath, workspaceName); |
| 88 | const skipRemoteSync = params.skipRemoteSync === true; |
| 89 | const trimmedStartPoint = params.startPoint?.trim(); |
| 90 | const startPoint = |
| 91 | trimmedStartPoint && trimmedStartPoint.length > 0 ? trimmedStartPoint : undefined; |
| 92 | let worktreeCreated = false; |
| 93 | let createdBranch = false; |
| 94 | |
| 95 | // Clean up stale lock before git operations on main repo |
| 96 | cleanStaleLock(projectPath); |
| 97 | |
| 98 | try { |
| 99 | initLogger.logStep("Creating git worktree..."); |
| 100 | |
| 101 | // Create parent directory if needed |
| 102 | const parentDir = path.dirname(workspacePath); |
| 103 | try { |
| 104 | await fsPromises.access(parentDir); |
| 105 | } catch { |
| 106 | await fsPromises.mkdir(parentDir, { recursive: true }); |
| 107 | } |
| 108 | |
| 109 | // Check if workspace already exists |
| 110 | try { |
| 111 | await fsPromises.access(workspacePath); |
| 112 | return { |
| 113 | success: false, |
| 114 | error: `Workspace already exists at ${workspacePath}`, |
| 115 | }; |
| 116 | } catch { |
| 117 | // Workspace doesn't exist, proceed with creation |
| 118 | } |
| 119 | |
| 120 | // Check if branch exists locally |
| 121 | const localBranches = await listLocalBranches(projectPath); |
| 122 | const branchExists = localBranches.includes(branchName); |
| 123 | |
| 124 | // Fetch origin before creating worktree (best-effort) |
| 125 | // This ensures new branches start from the latest origin state |
| 126 | const fetchedOrigin = skipRemoteSync |
no test coverage detected