ducklm/duck_core/tools/paths.py

30 lines
827 B
Python

from pathlib import Path
class WorkspacePathError(ValueError):
pass
def candidate_path(workspace: str, requested_path: str) -> Path:
root = Path(workspace).resolve()
path = Path(requested_path).expanduser()
if path.is_absolute():
return path.resolve()
return (root / path).resolve()
def is_inside_workspace(workspace: str, path: Path) -> bool:
root = Path(workspace).resolve()
if root != path and root not in path.parents:
return False
return True
def resolve_workspace_path(
workspace: str, relative_path: str, allow_outside: bool = False
) -> Path:
path = candidate_path(workspace, relative_path)
if not allow_outside and not is_inside_workspace(workspace, path):
raise WorkspacePathError(f"Path escapes workspace: {relative_path}")
return path