Show More
@@ -14,7 +14,7 b' use std::convert::From;' | |||
|
14 | 14 | use std::fmt; |
|
15 | 15 | use std::fs; |
|
16 | 16 | use std::io; |
|
17 | use std::path::PathBuf; | |
|
17 | use std::path::{Path, PathBuf}; | |
|
18 | 18 | |
|
19 | 19 | /// Kind of error encoutered by ListTrackedFiles |
|
20 | 20 | #[derive(Debug)] |
@@ -60,6 +60,15 b' impl ListTrackedFiles {' | |||
|
60 | 60 | let content = fs::read(&dirstate)?; |
|
61 | 61 | Ok(ListDirstateTrackedFiles { content }) |
|
62 | 62 | } |
|
63 | ||
|
64 | /// Returns the repository root directory | |
|
65 | /// TODO I think this is a crutch that creates a dependency that should not | |
|
66 | /// be there. Operations that need the root of the repository should get | |
|
67 | /// it themselves, probably in a lazy fashion. But this would make the | |
|
68 | /// current series even larger, so this is simplified for now. | |
|
69 | pub fn get_root(&self) -> &Path { | |
|
70 | &self.root | |
|
71 | } | |
|
63 | 72 | } |
|
64 | 73 | |
|
65 | 74 | /// List files under Mercurial control in the working directory |
@@ -16,7 +16,7 b' use crate::utils::{' | |||
|
16 | 16 | }; |
|
17 | 17 | use lazy_static::lazy_static; |
|
18 | 18 | use same_file::is_same_file; |
|
19 | use std::borrow::ToOwned; | |
|
19 | use std::borrow::{Cow, ToOwned}; | |
|
20 | 20 | use std::fs::Metadata; |
|
21 | 21 | use std::iter::FusedIterator; |
|
22 | 22 | use std::ops::Deref; |
@@ -248,6 +248,66 b' pub fn canonical_path(' | |||
|
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 | 311 | #[cfg(test)] |
|
252 | 312 | mod tests { |
|
253 | 313 | use super::*; |
@@ -2,6 +2,8 b' use crate::commands::Command;' | |||
|
2 | 2 | use crate::error::{CommandError, CommandErrorKind}; |
|
3 | 3 | use crate::ui::Ui; |
|
4 | 4 | use hg::operations::{ListTrackedFiles, ListTrackedFilesErrorKind}; |
|
5 | use hg::utils::files::{get_bytes_from_path, relativize_path}; | |
|
6 | use hg::utils::hg_path::HgPathBuf; | |
|
5 | 7 | |
|
6 | 8 | pub const HELP_TEXT: &str = " |
|
7 | 9 | List tracked files. |
@@ -38,9 +40,17 b" impl<'a> Command<'a> for FilesCommand<'a" | |||
|
38 | 40 | } |
|
39 | 41 | })?; |
|
40 | 42 | |
|
43 | let cwd = std::env::current_dir() | |
|
44 | .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; | |
|
45 | let rooted_cwd = cwd | |
|
46 | .strip_prefix(operation_builder.get_root()) | |
|
47 | .expect("cwd was already checked within the repository"); | |
|
48 | let rooted_cwd = HgPathBuf::from(get_bytes_from_path(rooted_cwd)); | |
|
49 | ||
|
41 | 50 | let mut stdout = self.ui.stdout_buffer(); |
|
51 | ||
|
42 | 52 | for file in files { |
|
43 |
stdout.write_all(file.as_ |
|
|
53 | stdout.write_all(relativize_path(file, &rooted_cwd).as_ref())?; | |
|
44 | 54 | stdout.write_all(b"\n")?; |
|
45 | 55 | } |
|
46 | 56 | stdout.flush()?; |
General Comments 0
You need to be logged in to leave comments.
Login now