Show More
@@ -5,7 +5,6 b'' | |||||
5 | // This software may be used and distributed according to the terms of the |
|
5 | // This software may be used and distributed according to the terms of the | |
6 | // GNU General Public License version 2 or any later version. |
|
6 | // GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | use super::find_root; |
|
|||
9 | use crate::dirstate::parsers::parse_dirstate; |
|
8 | use crate::dirstate::parsers::parse_dirstate; | |
10 | use crate::utils::hg_path::HgPath; |
|
9 | use crate::utils::hg_path::HgPath; | |
11 | use crate::{DirstateParseError, EntryState}; |
|
10 | use crate::{DirstateParseError, EntryState}; | |
@@ -13,74 +12,67 b' use rayon::prelude::*;' | |||||
13 | use std::convert::From; |
|
12 | use std::convert::From; | |
14 | use std::fmt; |
|
13 | use std::fmt; | |
15 | use std::fs; |
|
14 | use std::fs; | |
16 |
use std:: |
|
15 | use std::ops::Deref; | |
17 | use std::path::{Path, PathBuf}; |
|
16 | use std::path::{Path, PathBuf}; | |
18 |
|
17 | |||
19 | /// Kind of error encoutered by ListTrackedFiles |
|
18 | /// Kind of error encountered by `ListDirstateTrackedFiles` | |
20 | #[derive(Debug)] |
|
19 | #[derive(Debug)] | |
21 | pub enum ListTrackedFilesErrorKind { |
|
20 | pub enum ListDirstateTrackedFilesErrorKind { | |
|
21 | /// Error when reading the `dirstate` file | |||
|
22 | IoError(std::io::Error), | |||
|
23 | /// Error when parsing the `dirstate` file | |||
22 | ParseError(DirstateParseError), |
|
24 | ParseError(DirstateParseError), | |
23 | } |
|
25 | } | |
24 |
|
26 | |||
25 | /// A ListTrackedFiles error |
|
27 | /// A `ListDirstateTrackedFiles` error | |
26 | #[derive(Debug)] |
|
28 | #[derive(Debug)] | |
27 | pub struct ListTrackedFilesError { |
|
29 | pub struct ListDirstateTrackedFilesError { | |
28 | /// Kind of error encoutered by ListTrackedFiles |
|
30 | /// Kind of error encountered by `ListDirstateTrackedFiles` | |
29 | pub kind: ListTrackedFilesErrorKind, |
|
31 | pub kind: ListDirstateTrackedFilesErrorKind, | |
30 | } |
|
32 | } | |
31 |
|
33 | |||
32 | impl std::error::Error for ListTrackedFilesError {} |
|
34 | impl std::error::Error for ListDirstateTrackedFilesError {} | |
33 |
|
35 | |||
34 | impl fmt::Display for ListTrackedFilesError { |
|
36 | impl fmt::Display for ListDirstateTrackedFilesError { | |
35 | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { |
|
37 | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
36 | unimplemented!() |
|
38 | unimplemented!() | |
37 | } |
|
39 | } | |
38 | } |
|
40 | } | |
39 |
|
41 | |||
40 |
impl From<ListTrackedFilesErrorKind> |
|
42 | impl From<ListDirstateTrackedFilesErrorKind> | |
41 |
f |
|
43 | for ListDirstateTrackedFilesError | |
42 | ListTrackedFilesError { kind } |
|
44 | { | |
|
45 | fn from(kind: ListDirstateTrackedFilesErrorKind) -> Self { | |||
|
46 | ListDirstateTrackedFilesError { kind } | |||
43 | } |
|
47 | } | |
44 | } |
|
48 | } | |
45 |
|
49 | |||
46 | /// List files under Mercurial control in the working directory |
|
50 | impl From<std::io::Error> for ListDirstateTrackedFilesError { | |
47 | pub struct ListTrackedFiles { |
|
51 | fn from(err: std::io::Error) -> Self { | |
48 | root: PathBuf, |
|
52 | let kind = ListDirstateTrackedFilesErrorKind::IoError(err); | |
49 | } |
|
53 | ListDirstateTrackedFilesError { kind } | |
50 |
|
||||
51 | impl ListTrackedFiles { |
|
|||
52 | pub fn new() -> Result<Self, find_root::FindRootError> { |
|
|||
53 | let root = find_root::FindRoot::new().run()?; |
|
|||
54 | Ok(ListTrackedFiles { root }) |
|
|||
55 | } |
|
|||
56 |
|
||||
57 | /// Load the tracked files data from disk |
|
|||
58 | pub fn load(&self) -> Result<ListDirstateTrackedFiles, io::Error> { |
|
|||
59 | let dirstate = &self.root.join(".hg/dirstate"); |
|
|||
60 | let content = fs::read(&dirstate)?; |
|
|||
61 | Ok(ListDirstateTrackedFiles { content }) |
|
|||
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 | } |
|
54 | } | |
72 | } |
|
55 | } | |
73 |
|
56 | |||
74 | /// List files under Mercurial control in the working directory |
|
57 | /// List files under Mercurial control in the working directory | |
75 | /// by reading the dirstate |
|
58 | /// by reading the dirstate | |
76 | pub struct ListDirstateTrackedFiles { |
|
59 | pub struct ListDirstateTrackedFiles { | |
|
60 | /// The `dirstate` content. | |||
77 | content: Vec<u8>, |
|
61 | content: Vec<u8>, | |
78 | } |
|
62 | } | |
79 |
|
63 | |||
80 | impl ListDirstateTrackedFiles { |
|
64 | impl ListDirstateTrackedFiles { | |
81 |
pub fn |
|
65 | pub fn new(root: &PathBuf) -> Result<Self, ListDirstateTrackedFilesError> { | |
|
66 | let dirstate = root.join(".hg/dirstate"); | |||
|
67 | let content = fs::read(&dirstate)?; | |||
|
68 | Ok(Self { content }) | |||
|
69 | } | |||
|
70 | ||||
|
71 | pub fn run( | |||
|
72 | &mut self, | |||
|
73 | ) -> Result<Vec<&HgPath>, ListDirstateTrackedFilesError> { | |||
82 | let (_, entries, _) = parse_dirstate(&self.content) |
|
74 | let (_, entries, _) = parse_dirstate(&self.content) | |
83 | .map_err(ListTrackedFilesErrorKind::ParseError)?; |
|
75 | .map_err(ListDirstateTrackedFilesErrorKind::ParseError)?; | |
84 | let mut files: Vec<&HgPath> = entries |
|
76 | let mut files: Vec<&HgPath> = entries | |
85 | .into_iter() |
|
77 | .into_iter() | |
86 | .filter_map(|(path, entry)| match entry.state { |
|
78 | .filter_map(|(path, entry)| match entry.state { |
@@ -11,7 +11,8 b' pub use debugdata::{' | |||||
11 | }; |
|
11 | }; | |
12 | pub use find_root::{FindRoot, FindRootError, FindRootErrorKind}; |
|
12 | pub use find_root::{FindRoot, FindRootError, FindRootErrorKind}; | |
13 | pub use list_tracked_files::{ |
|
13 | pub use list_tracked_files::{ | |
14 |
ListTrackedFiles, List |
|
14 | ListDirstateTrackedFiles, ListDirstateTrackedFilesError, | |
|
15 | ListDirstateTrackedFilesErrorKind, | |||
15 | }; |
|
16 | }; | |
16 |
|
17 | |||
17 | // TODO add an `Operation` trait when GAT have landed (rust #44265): |
|
18 | // TODO add an `Operation` trait when GAT have landed (rust #44265): |
@@ -1,7 +1,12 b'' | |||||
1 | use crate::commands::Command; |
|
1 | use crate::commands::Command; | |
2 | use crate::error::{CommandError, CommandErrorKind}; |
|
2 | use crate::error::{CommandError, CommandErrorKind}; | |
|
3 | use crate::ui::utf8_to_local; | |||
3 | use crate::ui::Ui; |
|
4 | use crate::ui::Ui; | |
4 | use hg::operations::{ListTrackedFiles, ListTrackedFilesErrorKind}; |
|
5 | use hg::operations::FindRoot; | |
|
6 | use hg::operations::{ | |||
|
7 | ListDirstateTrackedFiles, ListDirstateTrackedFilesError, | |||
|
8 | ListDirstateTrackedFilesErrorKind, | |||
|
9 | }; | |||
5 | use hg::utils::files::{get_bytes_from_path, relativize_path}; |
|
10 | use hg::utils::files::{get_bytes_from_path, relativize_path}; | |
6 | use hg::utils::hg_path::HgPathBuf; |
|
11 | use hg::utils::hg_path::HgPathBuf; | |
7 |
|
12 | |||
@@ -21,27 +26,15 b' impl FilesCommand {' | |||||
21 |
|
26 | |||
22 | impl Command for FilesCommand { |
|
27 | impl Command for FilesCommand { | |
23 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { |
|
28 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
24 | let operation_builder = ListTrackedFiles::new()?; |
|
29 | let root = FindRoot::new().run()?; | |
25 | let operation = operation_builder.load().map_err(|err| { |
|
30 | let mut operation = ListDirstateTrackedFiles::new(&root) | |
26 | CommandErrorKind::Abort(Some( |
|
31 | .map_err(map_dirstate_error)?; | |
27 | [b"abort: ", err.to_string().as_bytes(), b"\n"] |
|
32 | let files = operation.run().map_err(map_dirstate_error)?; | |
28 | .concat() |
|
|||
29 | .to_vec(), |
|
|||
30 | )) |
|
|||
31 | })?; |
|
|||
32 | let files = operation.run().map_err(|err| match err.kind { |
|
|||
33 | ListTrackedFilesErrorKind::ParseError(_) => { |
|
|||
34 | CommandErrorKind::Abort(Some( |
|
|||
35 | // TODO find a better error message |
|
|||
36 | b"abort: parse error\n".to_vec(), |
|
|||
37 | )) |
|
|||
38 | } |
|
|||
39 | })?; |
|
|||
40 |
|
33 | |||
41 | let cwd = std::env::current_dir() |
|
34 | let cwd = std::env::current_dir() | |
42 | .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; |
|
35 | .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; | |
43 | let rooted_cwd = cwd |
|
36 | let rooted_cwd = cwd | |
44 |
.strip_prefix( |
|
37 | .strip_prefix(&root) | |
45 | .expect("cwd was already checked within the repository"); |
|
38 | .expect("cwd was already checked within the repository"); | |
46 | let rooted_cwd = HgPathBuf::from(get_bytes_from_path(rooted_cwd)); |
|
39 | let rooted_cwd = HgPathBuf::from(get_bytes_from_path(rooted_cwd)); | |
47 |
|
40 | |||
@@ -52,7 +45,25 b' impl Command for FilesCommand {' | |||||
52 | stdout.write_all(b"\n")?; |
|
45 | stdout.write_all(b"\n")?; | |
53 | } |
|
46 | } | |
54 | stdout.flush()?; |
|
47 | stdout.flush()?; | |
55 |
|
||||
56 | Ok(()) |
|
48 | Ok(()) | |
57 | } |
|
49 | } | |
58 | } |
|
50 | } | |
|
51 | ||||
|
52 | /// Convert operation errors to command errors | |||
|
53 | fn map_dirstate_error(err: ListDirstateTrackedFilesError) -> CommandError { | |||
|
54 | CommandError { | |||
|
55 | kind: match err.kind { | |||
|
56 | ListDirstateTrackedFilesErrorKind::IoError(err) => { | |||
|
57 | CommandErrorKind::Abort(Some( | |||
|
58 | utf8_to_local(&format!("abort: {}\n", err)).into(), | |||
|
59 | )) | |||
|
60 | } | |||
|
61 | ListDirstateTrackedFilesErrorKind::ParseError(_) => { | |||
|
62 | CommandErrorKind::Abort(Some( | |||
|
63 | // TODO find a better error message | |||
|
64 | b"abort: parse error\n".to_vec(), | |||
|
65 | )) | |||
|
66 | } | |||
|
67 | }, | |||
|
68 | } | |||
|
69 | } |
General Comments 0
You need to be logged in to leave comments.
Login now