##// END OF EJS Templates
hg-core: simplify `list_tracked_files` operation...
Antoine Cezar -
r46106:72b7d58d default
parent child Browse files
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::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 {
@@ -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, ListTrackedFilesError, ListTrackedFilesErrorKind,
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(operation_builder.get_root())
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