- Add pi-worktree-switch.ts with pure functions: - validateSwitchInput: validates target is non-empty - resolveWorktreeTarget: resolves path or branch name to worktree path - isAlreadyInWorktree: checks if cwd matches target - Wire up createSwitchWorktreeTool with full validation pipeline: 1. Validate input parameters 2. List worktrees and resolve target to path 3. Refuse if already in target worktree 4. Fail fast on uncommitted changes in source 5. Change cwd via ctx.chdir() 6. Return success with branch info - Remove dead resolveWorktreeTarget from main module - 21 unit tests, 103 total passing, 0 regressions
68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
/**
|
|
* Git worktree switch — pure validation and resolution functions.
|
|
* No pi SDK dependencies for testability.
|
|
*/
|
|
|
|
import path from "path";
|
|
import type { WorktreeError } from "./pi-worktree-create";
|
|
import type { WorktreeEntry } from "./pi-worktree-parser";
|
|
|
|
// ─── Input Validation ──────────────────────────────────────────────
|
|
|
|
/**
|
|
* Validate input parameters for switching worktrees.
|
|
*
|
|
* Checks that target is non-empty and well-formed.
|
|
*
|
|
* @param target - Path or branch name of the target worktree
|
|
* @returns null if valid, or a WorktreeError describing the problem
|
|
*/
|
|
export function validateSwitchInput(target: string): WorktreeError | null {
|
|
if (!target || !target.trim()) {
|
|
return {
|
|
message: "Target cannot be empty.",
|
|
suggestion: "Provide a valid worktree path or branch name. Use git_worktree_list to see available worktrees.",
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// ─── Target Resolution ──────────────────────────────────────────────
|
|
|
|
/**
|
|
* Resolve a worktree target (path or branch name) to its full path.
|
|
*
|
|
* First tries an exact path match, then falls back to branch name lookup.
|
|
*
|
|
* @param target - Path or branch name to resolve
|
|
* @param worktrees - List of all worktrees
|
|
* @returns The resolved path, or undefined if not found
|
|
*/
|
|
export function resolveWorktreeTarget(
|
|
target: string,
|
|
worktrees: WorktreeEntry[],
|
|
): string | undefined {
|
|
// Try exact path match first
|
|
const exactMatch = worktrees.find((w) => w.path === target);
|
|
if (exactMatch) return exactMatch.path;
|
|
|
|
// Fall back to branch name match
|
|
const branchMatch = worktrees.find((w) => w.branch === target);
|
|
return branchMatch?.path;
|
|
}
|
|
|
|
// ─── Already-There Check ───────────────────────────────────────────
|
|
|
|
/**
|
|
* Check if the current working directory is already the target worktree.
|
|
*
|
|
* Compares resolved paths to handle trailing slashes and relative paths.
|
|
*
|
|
* @param targetPath - The target worktree path
|
|
* @param currentCwd - Current working directory
|
|
* @returns true if already in the target worktree
|
|
*/
|
|
export function isAlreadyInWorktree(targetPath: string, currentCwd: string): boolean {
|
|
return path.resolve(currentCwd, targetPath) === path.resolve(currentCwd);
|
|
}
|