2ea2159d80
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
51 lines
2.3 KiB
TypeScript
51 lines
2.3 KiB
TypeScript
import { existsSync, realpathSync } from "node:fs";
|
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
|
|
export function normalizeWorkspaceDirectory(workspaceDirectory: string): string {
|
|
return realpathSync(resolve(workspaceDirectory));
|
|
}
|
|
|
|
export function resolveWorkspacePaths(rawPaths: readonly string[] | undefined, workspaceDirectory: string): readonly string[] {
|
|
const workspace = normalizeWorkspaceDirectory(workspaceDirectory);
|
|
const requestedPaths = rawPaths && rawPaths.length > 0 ? rawPaths : ["."];
|
|
return requestedPaths.map((rawPath) => resolveWorkspacePath(rawPath, workspace));
|
|
}
|
|
|
|
function resolveWorkspacePath(rawPath: string, workspaceDirectory: string): string {
|
|
if (rawPath.length === 0) throw new Error("paths entries must be non-empty strings");
|
|
if (rawPath.startsWith("-")) throw new Error(`paths entries must not start with '-': ${rawPath}`);
|
|
if (rawPath.includes("\0")) throw new Error("paths entries must not contain null bytes");
|
|
if (isAbsolute(rawPath)) return resolveAbsoluteWorkspacePath(rawPath, workspaceDirectory);
|
|
|
|
const absolutePath = resolve(workspaceDirectory, rawPath);
|
|
assertInsideWorkspace(absolutePath, workspaceDirectory, rawPath);
|
|
|
|
if (existsSync(absolutePath)) {
|
|
const realPath = realpathSync(absolutePath);
|
|
assertInsideWorkspace(realPath, workspaceDirectory, rawPath);
|
|
}
|
|
|
|
const normalizedPath = relative(workspaceDirectory, absolutePath);
|
|
return normalizedPath === "" ? "." : normalizedPath;
|
|
}
|
|
|
|
function resolveAbsoluteWorkspacePath(rawPath: string, workspaceDirectory: string): string {
|
|
let realPath: string;
|
|
try {
|
|
realPath = realpathSync(rawPath);
|
|
} catch {
|
|
throw new Error(`absolute path entry does not exist: ${rawPath}`);
|
|
}
|
|
|
|
assertInsideWorkspace(realPath, workspaceDirectory, rawPath);
|
|
|
|
const normalizedPath = relative(workspaceDirectory, realPath);
|
|
return normalizedPath === "" ? "." : normalizedPath;
|
|
}
|
|
|
|
function assertInsideWorkspace(candidatePath: string, workspaceDirectory: string, rawPath: string): void {
|
|
const workspaceRelativePath = relative(workspaceDirectory, candidatePath);
|
|
if (workspaceRelativePath === "" || (!workspaceRelativePath.startsWith("..") && !isAbsolute(workspaceRelativePath))) return;
|
|
throw new Error(`paths entries must stay inside the workspace: ${rawPath}`);
|
|
}
|