3 // Copyright 2020 Antoine Cezar <antoine.cezar@octobus.net> |
3 // Copyright 2020 Antoine Cezar <antoine.cezar@octobus.net> |
4 // |
4 // |
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}; |
12 use rayon::prelude::*; |
11 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::io; |
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> for ListTrackedFilesError { |
42 impl From<ListDirstateTrackedFilesErrorKind> |
41 fn from(kind: ListTrackedFilesErrorKind) -> Self { |
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 run(&self) -> Result<Vec<&HgPath>, ListTrackedFilesError> { |
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 { |
87 EntryState::Removed => None, |
79 EntryState::Removed => None, |
88 _ => Some(path), |
80 _ => Some(path), |