export type Workspace = { environment: string; cwd: string; platform: string }; export type Project = { name: string; roots: Workspace[]; defaultRoot: number }; export type ProjectInput = { name: string; roots: { environment: string; cwd: string }[]; defaultRoot: number; moveConversations?: boolean; }; export type ProjectIndex = Record; export function workspacePath(path: string, platform: string): string { const normalized = platform === "win32" ? path.replaceAll("\\", "/").toLowerCase() : path; return normalized.replace(/\/+$/u, "") || "/"; } /** The most specific workspace of this project containing the directory. */ export function workspaceFor( project: Project, binding: { environment: string; cwd: string } | undefined, ): Workspace | null { if (!binding) return null; let match: Workspace | null = null; let specificity = -1; for (const root of project.roots) { if (root.environment !== binding.environment) continue; const path = workspacePath(binding.cwd, root.platform); const base = workspacePath(root.cwd, root.platform); if ( (path === base || path.startsWith(base === "/" ? "/" : base + "/")) && base.length > specificity ) { match = root; specificity = base.length; } } return match; } /** The most specific workspace containing this directory, independent of fork ancestry. */ export function projectFor( projects: ProjectIndex, binding: { environment: string; cwd: string } | undefined, ): string | null { if (!binding) return null; let match: string | null = null; let specificity = -1; for (const [id, project] of Object.entries(projects)) { const root = workspaceFor(project, binding); if (!root) continue; const length = workspacePath(root.cwd, root.platform).length; if (length > specificity) { match = id; specificity = length; } } return match; }