Mercurial > public > mercurial-scm > hg
annotate 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 |
rev | line source |
---|---|
48174
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
1 // path utils module |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
2 // |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
3 // This software may be used and distributed according to the terms of the |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
4 // GNU General Public License version 2 or any later version. |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
5 |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48174
diff
changeset
|
6 use hg::errors::HgError; |
48174
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
7 use hg::repo::Repo; |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
8 use hg::utils::current_dir; |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
9 use hg::utils::files::{get_bytes_from_path, relativize_path}; |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
10 use hg::utils::hg_path::HgPath; |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
11 use hg::utils::hg_path::HgPathBuf; |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
12 use std::borrow::Cow; |
52541
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
13 use std::ffi::OsString; |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
14 |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
15 use crate::error::CommandError; |
48174
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
16 |
48453
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
17 pub struct RelativizePaths { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
18 repo_root: HgPathBuf, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
19 cwd: HgPathBuf, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
20 outside_repo: bool, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
21 } |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
22 |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
23 impl RelativizePaths { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
24 pub fn new(repo: &Repo) -> Result<Self, HgError> { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
25 let cwd = current_dir()?; |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
26 let repo_root = repo.working_directory_path(); |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
27 let repo_root = cwd.join(repo_root); // Make it absolute |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
28 let repo_root_hgpath = |
49914
58074252db3c
rust: run `cargo clippy`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48453
diff
changeset
|
29 HgPathBuf::from(get_bytes_from_path(&repo_root)); |
48174
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
30 |
48453
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
31 if let Ok(cwd_relative_to_repo) = cwd.strip_prefix(&repo_root) { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
32 // The current directory is inside the repo, so we can work with |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
33 // relative paths |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
34 Ok(Self { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
35 repo_root: repo_root_hgpath, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
36 cwd: HgPathBuf::from(get_bytes_from_path( |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
37 cwd_relative_to_repo, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
38 )), |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
39 outside_repo: false, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
40 }) |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
41 } else { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
42 Ok(Self { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
43 repo_root: repo_root_hgpath, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
44 cwd: HgPathBuf::from(get_bytes_from_path(cwd)), |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
45 outside_repo: true, |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
46 }) |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
47 } |
48174
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
48 } |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
49 |
48453
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
50 pub fn relativize<'a>(&self, path: &'a HgPath) -> Cow<'a, [u8]> { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
51 if self.outside_repo { |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
52 let joined = self.repo_root.join(path); |
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
53 Cow::Owned(relativize_path(&joined, &self.cwd).into_owned()) |
48174
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
54 } else { |
48453
9b0e1f64656f
rhg: refactor relativize_path into a struct + method
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
55 relativize_path(path, &self.cwd) |
48174
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
56 } |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
57 } |
9ecf802b06e0
rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff
changeset
|
58 } |
52541
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
59 |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
60 /// Resolves `FILE ...` arguments to a list of paths in the repository. |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
61 pub fn resolve_file_args<'a>( |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
62 repo: &Repo, |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
63 file_args: impl Iterator<Item = &'a OsString>, |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
64 ) -> Result<Vec<HgPathBuf>, CommandError> { |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
65 let cwd = hg::utils::current_dir()?; |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
66 let root = cwd.join(repo.working_directory_path()); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
67 let mut result = Vec::new(); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
68 for pattern in file_args { |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
69 // TODO: Support all the formats in `hg help patterns`. |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
70 if pattern.as_encoded_bytes().contains(&b':') { |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
71 return Err(CommandError::unsupported( |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
72 "rhg does not support file patterns", |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
73 )); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
74 } |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
75 // TODO: use hg::utils::files::canonical_path (currently doesn't work). |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
76 let path = cwd.join(pattern); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
77 let dotted = path.components().any(|c| c.as_os_str() == ".."); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
78 if pattern.as_encoded_bytes() == b"." || dotted { |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
79 let message = "`..` or `.` path segment"; |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
80 return Err(CommandError::unsupported(message)); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
81 } |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
82 let relative_path = root.strip_prefix(&cwd).unwrap_or(&root); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
83 let stripped = path.strip_prefix(&root).map_err(|_| { |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
84 CommandError::abort(format!( |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
85 "abort: {} not under root '{}'\n(consider using '--cwd {}')", |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
86 String::from_utf8_lossy(pattern.as_encoded_bytes()), |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
87 root.display(), |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
88 relative_path.display(), |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
89 )) |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
90 })?; |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
91 let hg_file = HgPathBuf::try_from(stripped.to_path_buf()) |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
92 .map_err(|e| CommandError::abort(e.to_string()))?; |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
93 result.push(hg_file); |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
94 } |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
95 Ok(result) |
f33f37accb43
rhg: add resolve_file_args to path_utils.rs
Mitchell Kember <mkember@janestreet.com>
parents:
49914
diff
changeset
|
96 } |