// Where `pnpm wt` puts a worktree — the one thing `add` and `rm` have to agree // about. Pure: no repo, no git, no filesystem. // // Run with: pnpm test:scripts import assert from "node:assert/strict"; import test from "node:test"; import path from "node:path"; import { indexForPath, worktreeDirFor } from "./worktree.mjs"; const MAIN = "/home/u/Projects/yt-dlp-transcript-browser"; const SIBLING = path.dirname(MAIN); test("a branch with a slash becomes one sibling directory", () => { // THE BUG: `add` flattened and `rm` did not, so `pnpm wt rm tags/site` — // the exact string the person had just passed to `add` — pointed git at a // path that had never existed. assert.equal(worktreeDirFor(MAIN, "tags/site"), path.join(SIBLING, "tags-site")); assert.equal( worktreeDirFor(MAIN, "one-core/phase-2/gate-a"), path.join(SIBLING, "one-core-phase-2-gate-a"), ); }); test("a plain name is unchanged, dots and dashes survive", () => { assert.equal(worktreeDirFor(MAIN, "hotfix"), path.join(SIBLING, "hotfix")); assert.equal( worktreeDirFor(MAIN, "release-1.2_rc"), path.join(SIBLING, "release-1.2_rc"), ); }); test("an absolute path passes through untouched", () => { // `rm` accepts one because it is what `list` prints; sanitizing it would eat // its separators and aim git at a directory that does not exist. const abs = path.join(SIBLING, "tags-site"); assert.equal(worktreeDirFor(MAIN, abs), abs); assert.equal(worktreeDirFor(MAIN, "/tmp/wt/some thing"), "/tmp/wt/some thing"); }); test("nothing escapes the sibling directory", () => { // A relative name cannot climb out: every "/" and "." run that could form a // traversal is flattened to dashes first. const dir = worktreeDirFor(MAIN, "../../etc/passwd"); assert.equal(dir, path.join(SIBLING, "..-..-etc-passwd")); assert.equal(path.dirname(dir), SIBLING); }); test("a worktree nested in the main checkout gets its OWN index, not the main one's", () => { // `.claude/worktrees/` lives INSIDE the main checkout. A first-match // walk found the main root first and gave every such worktree offset 0 -- // the main checkout's ports -- so two agents' umtool suites bound the same // 3051/3052. const roots = [MAIN, path.join(SIBLING, "feature-x"), path.join(MAIN, ".claude", "worktrees", "agent-1")]; assert.equal(indexForPath(roots, MAIN), 0); assert.equal(indexForPath(roots, path.join(MAIN, "umtool")), 0); assert.equal(indexForPath(roots, path.join(SIBLING, "feature-x", "editor")), 1); assert.equal(indexForPath(roots, path.join(MAIN, ".claude", "worktrees", "agent-1")), 2); assert.equal(indexForPath(roots, path.join(MAIN, ".claude", "worktrees", "agent-1", "umtool")), 2); // A sibling whose name only STARTS like the main root is not inside it. assert.equal(indexForPath(roots, `${MAIN}-other`), 0); assert.equal(indexForPath(roots, "/elsewhere"), 0); });