( config: Config, projectPath: string, branchName: string, options: CreateWorktreeOptions )
| 106 | } |
| 107 | |
| 108 | export async function createWorktree( |
| 109 | config: Config, |
| 110 | projectPath: string, |
| 111 | branchName: string, |
| 112 | options: CreateWorktreeOptions |
| 113 | ): Promise<WorktreeResult> { |
| 114 | // Clean up stale lock before git operations on main repo |
| 115 | cleanStaleLock(projectPath); |
| 116 | |
| 117 | try { |
| 118 | // Use directoryName if provided, otherwise fall back to branchName (legacy) |
| 119 | const dirName = options.directoryName ?? branchName; |
| 120 | // Compute workspace path using Runtime (single source of truth) |
| 121 | const runtime = createRuntime( |
| 122 | options.runtimeConfig ?? { type: "local", srcBaseDir: config.srcDir }, |
| 123 | { projectPath } |
| 124 | ); |
| 125 | const workspacePath = runtime.getWorkspacePath(projectPath, dirName); |
| 126 | const { trunkBranch } = options; |
| 127 | const normalizedTrunkBranch = typeof trunkBranch === "string" ? trunkBranch.trim() : ""; |
| 128 | |
| 129 | if (!normalizedTrunkBranch) { |
| 130 | return { |
| 131 | success: false, |
| 132 | error: "Trunk branch is required to create a workspace", |
| 133 | }; |
| 134 | } |
| 135 | |
| 136 | console.assert( |
| 137 | normalizedTrunkBranch.length > 0, |
| 138 | "Expected trunk branch to be validated before calling createWorktree" |
| 139 | ); |
| 140 | |
| 141 | // Create workspace directory if it doesn't exist |
| 142 | if (!fs.existsSync(path.dirname(workspacePath))) { |
| 143 | fs.mkdirSync(path.dirname(workspacePath), { recursive: true }); |
| 144 | } |
| 145 | |
| 146 | // Check if workspace already exists |
| 147 | if (fs.existsSync(workspacePath)) { |
| 148 | return { |
| 149 | success: false, |
| 150 | error: `Workspace already exists at ${workspacePath}`, |
| 151 | }; |
| 152 | } |
| 153 | |
| 154 | const localBranches = await listLocalBranches(projectPath); |
| 155 | |
| 156 | // If branch already exists locally, reuse it instead of creating a new one |
| 157 | if (localBranches.includes(branchName)) { |
| 158 | using proc = execFileAsync("git", [ |
| 159 | "-C", |
| 160 | projectPath, |
| 161 | "worktree", |
| 162 | "add", |
| 163 | workspacePath, |
| 164 | branchName, |
| 165 | ]); |
no test coverage detected