(root: &Path, input: &str)
| 594 | } |
| 595 | |
| 596 | pub(super) fn normalize_local_path(root: &Path, input: &str) -> Result<WorkspacePath> { |
| 597 | let input = default_path_input(input); |
| 598 | let candidate = Path::new(input); |
| 599 | |
| 600 | if candidate.is_absolute() { |
| 601 | let root = normalize_absolute_path(root)?; |
| 602 | let target = normalize_absolute_path(candidate)?; |
| 603 | if !target.starts_with(&root) { |
| 604 | bail!( |
| 605 | "Workspace boundary violation: path '{}' escapes workspace '{}'", |
| 606 | input, |
| 607 | root.display() |
| 608 | ); |
| 609 | } |
| 610 | let relative = target |
| 611 | .strip_prefix(&root) |
| 612 | .map_err(|_| anyhow!("Failed to compute workspace-relative path"))?; |
| 613 | return Ok(pathbuf_to_workspace_path(relative)); |
| 614 | } |
| 615 | |
| 616 | if has_windows_path_prefix(input) { |
| 617 | bail!("Absolute paths are not supported by this workspace backend"); |
| 618 | } |
| 619 | |
| 620 | let normalized_input = input.replace('\\', "/"); |
| 621 | let path = Path::new(&normalized_input); |
| 622 | if path.is_absolute() { |
| 623 | bail!("Absolute paths are not supported by this workspace backend"); |
| 624 | } |
| 625 | |
| 626 | let relative = normalize_relative_path(path)?; |
| 627 | Ok(pathbuf_to_workspace_path(&relative)) |
| 628 | } |
| 629 | |
| 630 | fn normalize_absolute_path(path: &Path) -> Result<PathBuf> { |
| 631 | let lexical = normalize_absolute_path_lexical(path)?; |
no test coverage detected