Mercurial > public > mercurial-scm > hg
comparison rust/hg-core/src/utils/files.rs @ 45436:1b3197047f5c
rhg: make output of `files` relative to the current directory and the root
This matches the behavior of `hg files`.
The util is added in `hg-core` instead of `rhg` because this operation could
be useful for other external tools. (this was definitely not prompted by rust
issue #50784, I swear)
Differential Revision: https://phab.mercurial-scm.org/D8872
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Thu, 30 Jul 2020 16:55:44 +0200 |
parents | 26114bd6ec60 |
children | 95d6f31e88db |
comparison
equal
deleted
inserted
replaced
45435:64de86fd0984 | 45436:1b3197047f5c |
---|---|
14 path_auditor::PathAuditor, | 14 path_auditor::PathAuditor, |
15 replace_slice, | 15 replace_slice, |
16 }; | 16 }; |
17 use lazy_static::lazy_static; | 17 use lazy_static::lazy_static; |
18 use same_file::is_same_file; | 18 use same_file::is_same_file; |
19 use std::borrow::ToOwned; | 19 use std::borrow::{Cow, ToOwned}; |
20 use std::fs::Metadata; | 20 use std::fs::Metadata; |
21 use std::iter::FusedIterator; | 21 use std::iter::FusedIterator; |
22 use std::ops::Deref; | 22 use std::ops::Deref; |
23 use std::path::{Path, PathBuf}; | 23 use std::path::{Path, PathBuf}; |
24 | 24 |
246 root: root.to_owned(), | 246 root: root.to_owned(), |
247 }) | 247 }) |
248 } | 248 } |
249 } | 249 } |
250 | 250 |
251 /// Returns the representation of the path relative to the current working | |
252 /// directory for display purposes. | |
253 /// | |
254 /// `cwd` is a `HgPath`, so it is considered relative to the root directory | |
255 /// of the repository. | |
256 /// | |
257 /// # Examples | |
258 /// | |
259 /// ``` | |
260 /// use hg::utils::hg_path::HgPath; | |
261 /// use hg::utils::files::relativize_path; | |
262 /// use std::borrow::Cow; | |
263 /// | |
264 /// let file = HgPath::new(b"nested/file"); | |
265 /// let cwd = HgPath::new(b""); | |
266 /// assert_eq!(relativize_path(file, cwd), Cow::Borrowed(b"nested/file")); | |
267 /// | |
268 /// let cwd = HgPath::new(b"nested"); | |
269 /// assert_eq!(relativize_path(file, cwd), Cow::Borrowed(b"file")); | |
270 /// | |
271 /// let cwd = HgPath::new(b"other"); | |
272 /// assert_eq!(relativize_path(file, cwd), Cow::Borrowed(b"../nested/file")); | |
273 /// ``` | |
274 pub fn relativize_path(path: &HgPath, cwd: impl AsRef<HgPath>) -> Cow<[u8]> { | |
275 if cwd.as_ref().is_empty() { | |
276 Cow::Borrowed(path.as_bytes()) | |
277 } else { | |
278 let mut res: Vec<u8> = Vec::new(); | |
279 let mut path_iter = path.as_bytes().split(|b| *b == b'/').peekable(); | |
280 let mut cwd_iter = | |
281 cwd.as_ref().as_bytes().split(|b| *b == b'/').peekable(); | |
282 loop { | |
283 match (path_iter.peek(), cwd_iter.peek()) { | |
284 (Some(a), Some(b)) if a == b => (), | |
285 _ => break, | |
286 } | |
287 path_iter.next(); | |
288 cwd_iter.next(); | |
289 } | |
290 let mut need_sep = false; | |
291 for _ in cwd_iter { | |
292 if need_sep { | |
293 res.extend(b"/") | |
294 } else { | |
295 need_sep = true | |
296 }; | |
297 res.extend(b".."); | |
298 } | |
299 for c in path_iter { | |
300 if need_sep { | |
301 res.extend(b"/") | |
302 } else { | |
303 need_sep = true | |
304 }; | |
305 res.extend(c); | |
306 } | |
307 Cow::Owned(res) | |
308 } | |
309 } | |
310 | |
251 #[cfg(test)] | 311 #[cfg(test)] |
252 mod tests { | 312 mod tests { |
253 use super::*; | 313 use super::*; |
254 use pretty_assertions::assert_eq; | 314 use pretty_assertions::assert_eq; |
255 | 315 |