Mercurial > public > mercurial-scm > hg
diff rust/rhg/src/utils/path_utils.rs @ 52541:f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Extracted logic for resolving `FILE ...` arguments from cat.rs into a new
function in path_utils.rs. I plan to use this for rhg annotate.
I tried to reuse hg::utils::files::canonical_path instead, but that didn't work.
For example it reports a InsideDotHg error for any path containing "..".
author | Mitchell Kember <mkember@janestreet.com> |
---|---|
date | Mon, 16 Dec 2024 10:52:01 -0500 |
parents | 58074252db3c |
children |
line wrap: on
line diff
--- a/rust/rhg/src/utils/path_utils.rs Thu Dec 19 00:18:33 2024 +0100 +++ b/rust/rhg/src/utils/path_utils.rs Mon Dec 16 10:52:01 2024 -0500 @@ -10,6 +10,9 @@ use hg::utils::hg_path::HgPath; use hg::utils::hg_path::HgPathBuf; use std::borrow::Cow; +use std::ffi::OsString; + +use crate::error::CommandError; pub struct RelativizePaths { repo_root: HgPathBuf, @@ -53,3 +56,41 @@ } } } + +/// Resolves `FILE ...` arguments to a list of paths in the repository. +pub fn resolve_file_args<'a>( + repo: &Repo, + file_args: impl Iterator<Item = &'a OsString>, +) -> Result<Vec<HgPathBuf>, CommandError> { + let cwd = hg::utils::current_dir()?; + let root = cwd.join(repo.working_directory_path()); + let mut result = Vec::new(); + for pattern in file_args { + // TODO: Support all the formats in `hg help patterns`. + if pattern.as_encoded_bytes().contains(&b':') { + return Err(CommandError::unsupported( + "rhg does not support file patterns", + )); + } + // TODO: use hg::utils::files::canonical_path (currently doesn't work). + let path = cwd.join(pattern); + let dotted = path.components().any(|c| c.as_os_str() == ".."); + if pattern.as_encoded_bytes() == b"." || dotted { + let message = "`..` or `.` path segment"; + return Err(CommandError::unsupported(message)); + } + let relative_path = root.strip_prefix(&cwd).unwrap_or(&root); + let stripped = path.strip_prefix(&root).map_err(|_| { + CommandError::abort(format!( + "abort: {} not under root '{}'\n(consider using '--cwd {}')", + String::from_utf8_lossy(pattern.as_encoded_bytes()), + root.display(), + relative_path.display(), + )) + })?; + let hg_file = HgPathBuf::try_from(stripped.to_path_buf()) + .map_err(|e| CommandError::abort(e.to_string()))?; + result.push(hg_file); + } + Ok(result) +}