30 lines
827 B
Python
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
|