(
projectPath: string,
oldName: string,
newName: string,
trusted?: boolean
)
| 362 | } |
| 363 | |
| 364 | async renameWorkspace( |
| 365 | projectPath: string, |
| 366 | oldName: string, |
| 367 | newName: string, |
| 368 | trusted?: boolean |
| 369 | ): Promise< |
| 370 | { success: true; oldPath: string; newPath: string } | { success: false; error: string } |
| 371 | > { |
| 372 | // Clean up stale lock before git operations on main repo |
| 373 | cleanStaleLock(projectPath); |
| 374 | |
| 375 | // Disable git hooks for untrusted projects |
| 376 | const noHooksEnv = this.getGitExecOptions(trusted); |
| 377 | |
| 378 | // Compute workspace paths using canonical method |
| 379 | const oldPath = this.getWorkspacePath(projectPath, oldName); |
| 380 | const newPath = this.getWorkspacePath(projectPath, newName); |
| 381 | |
| 382 | try { |
| 383 | // Move the worktree directory (updates git's internal worktree metadata) |
| 384 | using moveProc = execFileAsync( |
| 385 | "git", |
| 386 | ["-C", projectPath, "worktree", "move", oldPath, newPath], |
| 387 | noHooksEnv |
| 388 | ); |
| 389 | await moveProc.result; |
| 390 | |
| 391 | // Rename the tracked branch only when workspace identity still follows the old workspace |
| 392 | // name. Diverged workspaces keep their original branch and must not rename unrelated refs. |
| 393 | const originalBranchName = |
| 394 | (await this.getPersistedWorkspaceBranchName(projectPath, oldName)) ?? oldName; |
| 395 | let renamedBranchName = originalBranchName; |
| 396 | if (originalBranchName === oldName) { |
| 397 | try { |
| 398 | using branchProc = execFileAsync( |
| 399 | "git", |
| 400 | ["-C", newPath, "branch", "-m", oldName, newName], |
| 401 | noHooksEnv |
| 402 | ); |
| 403 | await branchProc.result; |
| 404 | renamedBranchName = newName; |
| 405 | } catch { |
| 406 | // Branch rename failed - this is fine, the directory was still moved. |
| 407 | } |
| 408 | } |
| 409 | |
| 410 | await this.updateWorkspaceBranchMapping(projectPath, oldName, newName, renamedBranchName); |
| 411 | return { success: true, oldPath, newPath }; |
| 412 | } catch (error) { |
| 413 | return { success: false, error: `Failed to rename workspace: ${getErrorMessage(error)}` }; |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | async canDeleteWorkspaceWithoutForce( |
| 418 | projectPath: string, |
nothing calls this directly
no test coverage detected