1import type { ThreadShell } from "./types";
2
3function normalizeWorktreePath(path: string | null): string | null {
4 const trimmed = path?.trim();
5 if (!trimmed) {
6 return null;
7 }
8 return trimmed;
9}
10
11export function getOrphanedWorktreePathForThread(
12 threads: ReadonlyArray<Pick<ThreadShell, "id" | "worktreePath">>,
13 threadId: ThreadShell["id"],
14): string | null {
15 const targetThread = threads.find((thread) => thread.id === threadId);
16 if (!targetThread) {
17 return null;
18 }
19
20 const targetWorktreePath = normalizeWorktreePath(targetThread.worktreePath);
21 if (!targetWorktreePath) {
22 return null;
23 }
24
25 const isShared = threads.some((thread) => {
26 if (thread.id === threadId) {
27 return false;
28 }
29 return normalizeWorktreePath(thread.worktreePath) === targetWorktreePath;
30 });
31
32 return isShared ? null : targetWorktreePath;
33}
34
35export function formatWorktreePathForDisplay(worktreePath: string): string {
36 const trimmed = worktreePath.trim();
37 if (!trimmed) {
38 return worktreePath;
39 }
40
41 const normalized = trimmed.replace(/\\/g, "/").replace(/\/+$/, "");
42 const parts = normalized.split("/");
43 const lastPart = parts[parts.length - 1]?.trim() ?? "";
44 return lastPart.length > 0 ? lastPart : trimmed;
45}