Show More
@@ -9,7 +9,7 b' use std::convert::From;' | |||||
9 | use std::path::{Path, PathBuf}; |
|
9 | use std::path::{Path, PathBuf}; | |
10 |
|
10 | |||
11 | use crate::revlog::changelog::Changelog; |
|
11 | use crate::revlog::changelog::Changelog; | |
12 |
use crate::revlog::manifest:: |
|
12 | use crate::revlog::manifest::Manifest; | |
13 | use crate::revlog::path_encode::path_encode; |
|
13 | use crate::revlog::path_encode::path_encode; | |
14 | use crate::revlog::revlog::Revlog; |
|
14 | use crate::revlog::revlog::Revlog; | |
15 | use crate::revlog::revlog::RevlogError; |
|
15 | use crate::revlog::revlog::RevlogError; | |
@@ -70,97 +70,60 b' impl From<RevlogError> for CatRevError {' | |||||
70 | } |
|
70 | } | |
71 |
|
71 | |||
72 | /// List files under Mercurial control at a given revision. |
|
72 | /// List files under Mercurial control at a given revision. | |
73 | pub struct CatRev<'a> { |
|
73 | /// | |
74 | root: &'a Path, |
|
74 | /// * `root`: Repository root | |
75 |
|
|
75 | /// * `rev`: The revision to cat the files from. | |
76 | rev: &'a str, |
|
76 | /// * `files`: The files to output. | |
77 | /// The files to output. |
|
77 | pub fn cat( | |
78 | files: &'a [HgPathBuf], |
|
78 | root: &Path, | |
79 | /// The changelog file |
|
79 | rev: &str, | |
80 | changelog: Changelog, |
|
80 | files: &[HgPathBuf], | |
81 | /// The manifest file |
|
81 | ) -> Result<Vec<u8>, CatRevError> { | |
82 | manifest: Manifest, |
|
82 | let changelog = Changelog::open(&root)?; | |
83 | /// The manifest entry corresponding to the revision. |
|
83 | let manifest = Manifest::open(&root)?; | |
84 | /// |
|
84 | ||
85 | /// Used to hold the owner of the returned references. |
|
85 | let changelog_entry = match rev.parse::<Revision>() { | |
86 | manifest_entry: Option<ManifestEntry>, |
|
86 | Ok(rev) => changelog.get_rev(rev)?, | |
87 | } |
|
87 | _ => { | |
|
88 | let changelog_node = NodePrefix::from_hex(&rev) | |||
|
89 | .map_err(|_| CatRevErrorKind::InvalidRevision)?; | |||
|
90 | changelog.get_node(changelog_node.borrow())? | |||
|
91 | } | |||
|
92 | }; | |||
|
93 | let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?) | |||
|
94 | .map_err(|_| CatRevErrorKind::CorruptedRevlog)?; | |||
|
95 | ||||
|
96 | let manifest_entry = manifest.get_node((&manifest_node).into())?; | |||
|
97 | let mut bytes = vec![]; | |||
88 |
|
98 | |||
89 | impl<'a> CatRev<'a> { |
|
99 | for (manifest_file, node_bytes) in manifest_entry.files_with_nodes() { | |
90 | pub fn new( |
|
100 | for cat_file in files.iter() { | |
91 | root: &'a Path, |
|
101 | if cat_file.as_bytes() == manifest_file.as_bytes() { | |
92 | rev: &'a str, |
|
102 | let index_path = store_path(root, manifest_file, b".i"); | |
93 | files: &'a [HgPathBuf], |
|
103 | let data_path = store_path(root, manifest_file, b".d"); | |
94 | ) -> Result<Self, CatRevError> { |
|
|||
95 | let changelog = Changelog::open(&root)?; |
|
|||
96 | let manifest = Manifest::open(&root)?; |
|
|||
97 | let manifest_entry = None; |
|
|||
98 |
|
104 | |||
99 | Ok(Self { |
|
105 | let file_log = Revlog::open(&index_path, Some(&data_path))?; | |
100 | root, |
|
106 | let file_node = Node::from_hex(node_bytes) | |
101 | rev, |
|
107 | .map_err(|_| CatRevErrorKind::CorruptedRevlog)?; | |
102 | files, |
|
108 | let file_rev = file_log.get_node_rev((&file_node).into())?; | |
103 | changelog, |
|
109 | let data = file_log.get_rev_data(file_rev)?; | |
104 | manifest, |
|
110 | if data.starts_with(&METADATA_DELIMITER) { | |
105 | manifest_entry, |
|
111 | let end_delimiter_position = data | |
106 | }) |
|
112 | [METADATA_DELIMITER.len()..] | |
|
113 | .windows(METADATA_DELIMITER.len()) | |||
|
114 | .position(|bytes| bytes == METADATA_DELIMITER); | |||
|
115 | if let Some(position) = end_delimiter_position { | |||
|
116 | let offset = METADATA_DELIMITER.len() * 2; | |||
|
117 | bytes.extend(data[position + offset..].iter()); | |||
|
118 | } | |||
|
119 | } else { | |||
|
120 | bytes.extend(data); | |||
|
121 | } | |||
|
122 | } | |||
|
123 | } | |||
107 | } |
|
124 | } | |
108 |
|
125 | |||
109 | pub fn run(&mut self) -> Result<Vec<u8>, CatRevError> { |
|
126 | Ok(bytes) | |
110 | let changelog_entry = match self.rev.parse::<Revision>() { |
|
|||
111 | Ok(rev) => self.changelog.get_rev(rev)?, |
|
|||
112 | _ => { |
|
|||
113 | let changelog_node = NodePrefix::from_hex(&self.rev) |
|
|||
114 | .map_err(|_| CatRevErrorKind::InvalidRevision)?; |
|
|||
115 | self.changelog.get_node(changelog_node.borrow())? |
|
|||
116 | } |
|
|||
117 | }; |
|
|||
118 | let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?) |
|
|||
119 | .map_err(|_| CatRevErrorKind::CorruptedRevlog)?; |
|
|||
120 |
|
||||
121 | self.manifest_entry = |
|
|||
122 | Some(self.manifest.get_node((&manifest_node).into())?); |
|
|||
123 | if let Some(ref manifest_entry) = self.manifest_entry { |
|
|||
124 | let mut bytes = vec![]; |
|
|||
125 |
|
||||
126 | for (manifest_file, node_bytes) in |
|
|||
127 | manifest_entry.files_with_nodes() |
|
|||
128 | { |
|
|||
129 | for cat_file in self.files.iter() { |
|
|||
130 | if cat_file.as_bytes() == manifest_file.as_bytes() { |
|
|||
131 | let index_path = |
|
|||
132 | store_path(self.root, manifest_file, b".i"); |
|
|||
133 | let data_path = |
|
|||
134 | store_path(self.root, manifest_file, b".d"); |
|
|||
135 |
|
||||
136 | let file_log = |
|
|||
137 | Revlog::open(&index_path, Some(&data_path))?; |
|
|||
138 | let file_node = Node::from_hex(node_bytes) |
|
|||
139 | .map_err(|_| CatRevErrorKind::CorruptedRevlog)?; |
|
|||
140 | let file_rev = |
|
|||
141 | file_log.get_node_rev((&file_node).into())?; |
|
|||
142 | let data = file_log.get_rev_data(file_rev)?; |
|
|||
143 | if data.starts_with(&METADATA_DELIMITER) { |
|
|||
144 | let end_delimiter_position = data |
|
|||
145 | [METADATA_DELIMITER.len()..] |
|
|||
146 | .windows(METADATA_DELIMITER.len()) |
|
|||
147 | .position(|bytes| bytes == METADATA_DELIMITER); |
|
|||
148 | if let Some(position) = end_delimiter_position { |
|
|||
149 | let offset = METADATA_DELIMITER.len() * 2; |
|
|||
150 | bytes.extend(data[position + offset..].iter()); |
|
|||
151 | } |
|
|||
152 | } else { |
|
|||
153 | bytes.extend(data); |
|
|||
154 | } |
|
|||
155 | } |
|
|||
156 | } |
|
|||
157 | } |
|
|||
158 |
|
||||
159 | Ok(bytes) |
|
|||
160 | } else { |
|
|||
161 | unreachable!("manifest_entry should have been stored"); |
|
|||
162 | } |
|
|||
163 | } |
|
|||
164 | } |
|
127 | } | |
165 |
|
128 | |||
166 | fn store_path(root: &Path, hg_path: &HgPath, suffix: &[u8]) -> PathBuf { |
|
129 | fn store_path(root: &Path, hg_path: &HgPath, suffix: &[u8]) -> PathBuf { |
@@ -5,7 +5,8 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; |
|
8 | use std::path::Path; | |
|
9 | ||||
9 | use crate::revlog::revlog::{Revlog, RevlogError}; |
|
10 | use crate::revlog::revlog::{Revlog, RevlogError}; | |
10 | use crate::revlog::NodePrefix; |
|
11 | use crate::revlog::NodePrefix; | |
11 | use crate::revlog::Revision; |
|
12 | use crate::revlog::Revision; | |
@@ -20,7 +21,6 b' pub enum DebugDataKind {' | |||||
20 | /// Kind of error encountered by DebugData |
|
21 | /// Kind of error encountered by DebugData | |
21 | #[derive(Debug)] |
|
22 | #[derive(Debug)] | |
22 | pub enum DebugDataErrorKind { |
|
23 | pub enum DebugDataErrorKind { | |
23 | FindRootError(find_root::FindRootError), |
|
|||
24 | /// Error when reading a `revlog` file. |
|
24 | /// Error when reading a `revlog` file. | |
25 | IoError(std::io::Error), |
|
25 | IoError(std::io::Error), | |
26 | /// The revision has not been found. |
|
26 | /// The revision has not been found. | |
@@ -48,13 +48,6 b' impl From<DebugDataErrorKind> for DebugD' | |||||
48 | } |
|
48 | } | |
49 | } |
|
49 | } | |
50 |
|
50 | |||
51 | impl From<find_root::FindRootError> for DebugDataError { |
|
|||
52 | fn from(err: find_root::FindRootError) -> Self { |
|
|||
53 | let kind = DebugDataErrorKind::FindRootError(err); |
|
|||
54 | DebugDataError { kind } |
|
|||
55 | } |
|
|||
56 | } |
|
|||
57 |
|
||||
58 | impl From<std::io::Error> for DebugDataError { |
|
51 | impl From<std::io::Error> for DebugDataError { | |
59 | fn from(err: std::io::Error) -> Self { |
|
52 | fn from(err: std::io::Error) -> Self { | |
60 | let kind = DebugDataErrorKind::IoError(err); |
|
53 | let kind = DebugDataErrorKind::IoError(err); | |
@@ -85,36 +78,26 b' impl From<RevlogError> for DebugDataErro' | |||||
85 | } |
|
78 | } | |
86 |
|
79 | |||
87 | /// Dump the contents data of a revision. |
|
80 | /// Dump the contents data of a revision. | |
88 | pub struct DebugData<'a> { |
|
81 | pub fn debug_data( | |
89 | /// Revision or hash of the revision. |
|
82 | root: &Path, | |
90 |
rev: & |
|
83 | rev: &str, | |
91 | /// Kind of data to debug. |
|
|||
92 | kind: DebugDataKind, |
|
84 | kind: DebugDataKind, | |
93 | } |
|
85 | ) -> Result<Vec<u8>, DebugDataError> { | |
94 |
|
86 | let index_file = match kind { | ||
95 | impl<'a> DebugData<'a> { |
|
87 | DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"), | |
96 | pub fn new(rev: &'a str, kind: DebugDataKind) -> Self { |
|
88 | DebugDataKind::Manifest => root.join(".hg/store/00manifest.i"), | |
97 | DebugData { rev, kind } |
|
89 | }; | |
98 | } |
|
90 | let revlog = Revlog::open(&index_file, None)?; | |
99 |
|
91 | |||
100 | pub fn run(&mut self) -> Result<Vec<u8>, DebugDataError> { |
|
92 | let data = match rev.parse::<Revision>() { | |
101 | let root = find_root::FindRoot::new().run()?; |
|
93 | Ok(rev) => revlog.get_rev_data(rev)?, | |
102 | let index_file = match self.kind { |
|
94 | _ => { | |
103 | DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"), |
|
95 | let node = NodePrefix::from_hex(&rev) | |
104 | DebugDataKind::Manifest => root.join(".hg/store/00manifest.i"), |
|
96 | .map_err(|_| DebugDataErrorKind::InvalidRevision)?; | |
105 | }; |
|
97 | let rev = revlog.get_node_rev(node.borrow())?; | |
106 | let revlog = Revlog::open(&index_file, None)?; |
|
98 | revlog.get_rev_data(rev)? | |
|
99 | } | |||
|
100 | }; | |||
107 |
|
101 | |||
108 | let data = match self.rev.parse::<Revision>() { |
|
102 | Ok(data) | |
109 | Ok(rev) => revlog.get_rev_data(rev)?, |
|
|||
110 | _ => { |
|
|||
111 | let node = NodePrefix::from_hex(&self.rev) |
|
|||
112 | .map_err(|_| DebugDataErrorKind::InvalidRevision)?; |
|
|||
113 | let rev = revlog.get_node_rev(node.borrow())?; |
|
|||
114 | revlog.get_rev_data(rev)? |
|
|||
115 | } |
|
|||
116 | }; |
|
|||
117 |
|
||||
118 | Ok(data) |
|
|||
119 | } |
|
|||
120 | } |
|
103 | } |
@@ -28,46 +28,29 b' impl fmt::Display for FindRootError {' | |||||
28 | } |
|
28 | } | |
29 |
|
29 | |||
30 | /// Find the root of the repository |
|
30 | /// Find the root of the repository | |
31 | /// by searching for a .hg directory in the current directory and its |
|
31 | /// by searching for a .hg directory in the process’ current directory and its | |
32 | /// ancestors |
|
32 | /// ancestors | |
33 | pub struct FindRoot<'a> { |
|
33 | pub fn find_root() -> Result<PathBuf, FindRootError> { | |
34 | current_dir: Option<&'a Path>, |
|
34 | let current_dir = std::env::current_dir().map_err(|e| FindRootError { | |
|
35 | kind: FindRootErrorKind::GetCurrentDirError(e), | |||
|
36 | })?; | |||
|
37 | Ok(find_root_from_path(¤t_dir)?.into()) | |||
35 | } |
|
38 | } | |
36 |
|
39 | |||
37 | impl<'a> FindRoot<'a> { |
|
40 | /// Find the root of the repository | |
38 | pub fn new() -> Self { |
|
41 | /// by searching for a .hg directory in the given directory and its ancestors | |
39 | Self { current_dir: None } |
|
42 | pub fn find_root_from_path(start: &Path) -> Result<&Path, FindRootError> { | |
|
43 | if start.join(".hg").exists() { | |||
|
44 | return Ok(start); | |||
40 | } |
|
45 | } | |
41 |
|
46 | for ancestor in start.ancestors() { | ||
42 | pub fn new_from_path(current_dir: &'a Path) -> Self { |
|
47 | if ancestor.join(".hg").exists() { | |
43 | Self { |
|
48 | return Ok(ancestor); | |
44 | current_dir: Some(current_dir), |
|
|||
45 | } |
|
49 | } | |
46 | } |
|
50 | } | |
47 |
|
51 | Err(FindRootError { | ||
48 | pub fn run(&self) -> Result<PathBuf, FindRootError> { |
|
52 | kind: FindRootErrorKind::RootNotFound(start.into()), | |
49 | let current_dir = match self.current_dir { |
|
53 | }) | |
50 | None => std::env::current_dir().or_else(|e| { |
|
|||
51 | Err(FindRootError { |
|
|||
52 | kind: FindRootErrorKind::GetCurrentDirError(e), |
|
|||
53 | }) |
|
|||
54 | })?, |
|
|||
55 | Some(path) => path.into(), |
|
|||
56 | }; |
|
|||
57 |
|
||||
58 | if current_dir.join(".hg").exists() { |
|
|||
59 | return Ok(current_dir); |
|
|||
60 | } |
|
|||
61 | let ancestors = current_dir.ancestors(); |
|
|||
62 | for parent in ancestors { |
|
|||
63 | if parent.join(".hg").exists() { |
|
|||
64 | return Ok(parent.into()); |
|
|||
65 | } |
|
|||
66 | } |
|
|||
67 | Err(FindRootError { |
|
|||
68 | kind: FindRootErrorKind::RootNotFound(current_dir.to_path_buf()), |
|
|||
69 | }) |
|
|||
70 | } |
|
|||
71 | } |
|
54 | } | |
72 |
|
55 | |||
73 | #[cfg(test)] |
|
56 | #[cfg(test)] | |
@@ -81,7 +64,7 b' mod tests {' | |||||
81 | let tmp_dir = tempfile::tempdir().unwrap(); |
|
64 | let tmp_dir = tempfile::tempdir().unwrap(); | |
82 | let path = tmp_dir.path(); |
|
65 | let path = tmp_dir.path(); | |
83 |
|
66 | |||
84 |
let err = |
|
67 | let err = find_root_from_path(&path).unwrap_err(); | |
85 |
|
68 | |||
86 | // TODO do something better |
|
69 | // TODO do something better | |
87 | assert!(match err { |
|
70 | assert!(match err { | |
@@ -98,7 +81,7 b' mod tests {' | |||||
98 | let root = tmp_dir.path(); |
|
81 | let root = tmp_dir.path(); | |
99 | fs::create_dir_all(root.join(".hg")).unwrap(); |
|
82 | fs::create_dir_all(root.join(".hg")).unwrap(); | |
100 |
|
83 | |||
101 |
let result = |
|
84 | let result = find_root_from_path(&root).unwrap(); | |
102 |
|
85 | |||
103 | assert_eq!(result, root) |
|
86 | assert_eq!(result, root) | |
104 | } |
|
87 | } | |
@@ -109,10 +92,8 b' mod tests {' | |||||
109 | let root = tmp_dir.path(); |
|
92 | let root = tmp_dir.path(); | |
110 | fs::create_dir_all(root.join(".hg")).unwrap(); |
|
93 | fs::create_dir_all(root.join(".hg")).unwrap(); | |
111 |
|
94 | |||
112 | let result = |
|
95 | let directory = root.join("some/nested/directory"); | |
113 | FindRoot::new_from_path(&root.join("some/nested/directory")) |
|
96 | let result = find_root_from_path(&directory).unwrap(); | |
114 | .run() |
|
|||
115 | .unwrap(); |
|
|||
116 |
|
97 | |||
117 | assert_eq!(result, root) |
|
98 | assert_eq!(result, root) | |
118 | } |
|
99 | } |
@@ -51,20 +51,20 b' impl From<std::io::Error> for ListDirsta' | |||||
51 |
|
51 | |||
52 | /// List files under Mercurial control in the working directory |
|
52 | /// List files under Mercurial control in the working directory | |
53 | /// by reading the dirstate |
|
53 | /// by reading the dirstate | |
54 |
pub struct |
|
54 | pub struct Dirstate { | |
55 | /// The `dirstate` content. |
|
55 | /// The `dirstate` content. | |
56 | content: Vec<u8>, |
|
56 | content: Vec<u8>, | |
57 | } |
|
57 | } | |
58 |
|
58 | |||
59 |
impl |
|
59 | impl Dirstate { | |
60 | pub fn new(root: &Path) -> Result<Self, ListDirstateTrackedFilesError> { |
|
60 | pub fn new(root: &Path) -> Result<Self, ListDirstateTrackedFilesError> { | |
61 | let dirstate = root.join(".hg/dirstate"); |
|
61 | let dirstate = root.join(".hg/dirstate"); | |
62 | let content = fs::read(&dirstate)?; |
|
62 | let content = fs::read(&dirstate)?; | |
63 | Ok(Self { content }) |
|
63 | Ok(Self { content }) | |
64 | } |
|
64 | } | |
65 |
|
65 | |||
66 |
pub fn |
|
66 | pub fn tracked_files( | |
67 |
& |
|
67 | &self, | |
68 | ) -> Result<Vec<&HgPath>, ListDirstateTrackedFilesError> { |
|
68 | ) -> Result<Vec<&HgPath>, ListDirstateTrackedFilesError> { | |
69 | let (_, entries, _) = parse_dirstate(&self.content) |
|
69 | let (_, entries, _) = parse_dirstate(&self.content) | |
70 | .map_err(ListDirstateTrackedFilesErrorKind::ParseError)?; |
|
70 | .map_err(ListDirstateTrackedFilesErrorKind::ParseError)?; | |
@@ -137,58 +137,31 b' impl From<RevlogError> for ListRevTracke' | |||||
137 | } |
|
137 | } | |
138 |
|
138 | |||
139 | /// List files under Mercurial control at a given revision. |
|
139 | /// List files under Mercurial control at a given revision. | |
140 |
pub |
|
140 | pub fn list_rev_tracked_files( | |
141 | /// The revision to list the files from. |
|
141 | root: &Path, | |
142 |
rev: & |
|
142 | rev: &str, | |
143 | /// The changelog file |
|
143 | ) -> Result<FilesForRev, ListRevTrackedFilesError> { | |
144 |
changelog |
|
144 | let changelog = Changelog::open(root)?; | |
145 | /// The manifest file |
|
145 | let manifest = Manifest::open(root)?; | |
146 | manifest: Manifest, |
|
146 | ||
147 | /// The manifest entry corresponding to the revision. |
|
147 | let changelog_entry = match rev.parse::<Revision>() { | |
148 | /// |
|
148 | Ok(rev) => changelog.get_rev(rev)?, | |
149 | /// Used to hold the owner of the returned references. |
|
149 | _ => { | |
150 | manifest_entry: Option<ManifestEntry>, |
|
150 | let changelog_node = NodePrefix::from_hex(&rev) | |
|
151 | .or(Err(ListRevTrackedFilesErrorKind::InvalidRevision))?; | |||
|
152 | changelog.get_node(changelog_node.borrow())? | |||
|
153 | } | |||
|
154 | }; | |||
|
155 | let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?) | |||
|
156 | .or(Err(ListRevTrackedFilesErrorKind::CorruptedRevlog))?; | |||
|
157 | let manifest_entry = manifest.get_node((&manifest_node).into())?; | |||
|
158 | Ok(FilesForRev(manifest_entry)) | |||
151 | } |
|
159 | } | |
152 |
|
160 | |||
153 | impl<'a> ListRevTrackedFiles<'a> { |
|
161 | pub struct FilesForRev(ManifestEntry); | |
154 | pub fn new( |
|
|||
155 | root: &Path, |
|
|||
156 | rev: &'a str, |
|
|||
157 | ) -> Result<Self, ListRevTrackedFilesError> { |
|
|||
158 | let changelog = Changelog::open(root)?; |
|
|||
159 | let manifest = Manifest::open(root)?; |
|
|||
160 |
|
||||
161 | Ok(Self { |
|
|||
162 | rev, |
|
|||
163 | changelog, |
|
|||
164 | manifest, |
|
|||
165 | manifest_entry: None, |
|
|||
166 | }) |
|
|||
167 | } |
|
|||
168 |
|
162 | |||
169 | pub fn run( |
|
163 | impl FilesForRev { | |
170 | &mut self, |
|
164 | pub fn iter(&self) -> impl Iterator<Item = &HgPath> { | |
171 | ) -> Result<impl Iterator<Item = &HgPath>, ListRevTrackedFilesError> { |
|
165 | self.0.files() | |
172 | let changelog_entry = match self.rev.parse::<Revision>() { |
|
|||
173 | Ok(rev) => self.changelog.get_rev(rev)?, |
|
|||
174 | _ => { |
|
|||
175 | let changelog_node = NodePrefix::from_hex(&self.rev) |
|
|||
176 | .or(Err(ListRevTrackedFilesErrorKind::InvalidRevision))?; |
|
|||
177 | self.changelog.get_node(changelog_node.borrow())? |
|
|||
178 | } |
|
|||
179 | }; |
|
|||
180 | let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?) |
|
|||
181 | .or(Err(ListRevTrackedFilesErrorKind::CorruptedRevlog))?; |
|
|||
182 |
|
||||
183 | self.manifest_entry = |
|
|||
184 | Some(self.manifest.get_node((&manifest_node).into())?); |
|
|||
185 |
|
||||
186 | if let Some(ref manifest_entry) = self.manifest_entry { |
|
|||
187 | Ok(manifest_entry.files()) |
|
|||
188 | } else { |
|
|||
189 | panic!( |
|
|||
190 | "manifest entry should have been stored in self.manifest_node to ensure its lifetime since references are returned from it" |
|
|||
191 | ) |
|
|||
192 | } |
|
|||
193 | } |
|
166 | } | |
194 | } |
|
167 | } |
@@ -7,22 +7,17 b' mod debugdata;' | |||||
7 | mod dirstate_status; |
|
7 | mod dirstate_status; | |
8 | mod find_root; |
|
8 | mod find_root; | |
9 | mod list_tracked_files; |
|
9 | mod list_tracked_files; | |
10 |
pub use cat::{ |
|
10 | pub use cat::{cat, CatRevError, CatRevErrorKind}; | |
11 | pub use debugdata::{ |
|
11 | pub use debugdata::{ | |
12 |
|
|
12 | debug_data, DebugDataError, DebugDataErrorKind, DebugDataKind, | |
13 | }; |
|
13 | }; | |
14 | pub use find_root::{FindRoot, FindRootError, FindRootErrorKind}; |
|
14 | pub use find_root::{ | |
15 | pub use list_tracked_files::{ |
|
15 | find_root, find_root_from_path, FindRootError, FindRootErrorKind, | |
16 | ListDirstateTrackedFiles, ListDirstateTrackedFilesError, |
|
|||
17 | ListDirstateTrackedFilesErrorKind, |
|
|||
18 | }; |
|
16 | }; | |
19 | pub use list_tracked_files::{ |
|
17 | pub use list_tracked_files::{ | |
20 |
|
|
18 | list_rev_tracked_files, FilesForRev, ListRevTrackedFilesError, | |
21 | ListRevTrackedFilesErrorKind, |
|
19 | ListRevTrackedFilesErrorKind, | |
22 | }; |
|
20 | }; | |
23 |
|
21 | pub use list_tracked_files::{ | ||
24 | // TODO add an `Operation` trait when GAT have landed (rust #44265): |
|
22 | Dirstate, ListDirstateTrackedFilesError, ListDirstateTrackedFilesErrorKind, | |
25 | // there is no way to currently define a trait which can both return |
|
23 | }; | |
26 | // references to `self` and to passed data, which is what we would need. |
|
|||
27 | // Generic Associated Types may fix this and allow us to have a unified |
|
|||
28 | // interface. |
|
@@ -2,8 +2,8 b' 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::utf8_to_local; | |
4 | use crate::ui::Ui; |
|
4 | use crate::ui::Ui; | |
5 |
use hg::operations:: |
|
5 | use hg::operations::find_root; | |
6 |
use hg::operations::{ |
|
6 | use hg::operations::{cat, CatRevError, CatRevErrorKind}; | |
7 | use hg::requirements; |
|
7 | use hg::requirements; | |
8 | use hg::utils::hg_path::HgPathBuf; |
|
8 | use hg::utils::hg_path::HgPathBuf; | |
9 | use micro_timer::timed; |
|
9 | use micro_timer::timed; | |
@@ -32,7 +32,7 b" impl<'a> CatCommand<'a> {" | |||||
32 | impl<'a> Command for CatCommand<'a> { |
|
32 | impl<'a> Command for CatCommand<'a> { | |
33 | #[timed] |
|
33 | #[timed] | |
34 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { |
|
34 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
35 |
let root = |
|
35 | let root = find_root()?; | |
36 | requirements::check(&root)?; |
|
36 | requirements::check(&root)?; | |
37 | let cwd = std::env::current_dir() |
|
37 | let cwd = std::env::current_dir() | |
38 | .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; |
|
38 | .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; | |
@@ -50,10 +50,8 b" impl<'a> Command for CatCommand<'a> {" | |||||
50 |
|
50 | |||
51 | match self.rev { |
|
51 | match self.rev { | |
52 | Some(rev) => { |
|
52 | Some(rev) => { | |
53 |
let |
|
53 | let data = cat(&root, rev, &files) | |
54 | .map_err(|e| map_rev_error(rev, e))?; |
|
54 | .map_err(|e| map_rev_error(rev, e))?; | |
55 | let data = |
|
|||
56 | operation.run().map_err(|e| map_rev_error(rev, e))?; |
|
|||
57 | self.display(ui, &data) |
|
55 | self.display(ui, &data) | |
58 | } |
|
56 | } | |
59 | None => Err(CommandErrorKind::Unimplemented.into()), |
|
57 | None => Err(CommandErrorKind::Unimplemented.into()), |
@@ -2,8 +2,9 b' 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::utf8_to_local; | |
4 | use crate::ui::Ui; |
|
4 | use crate::ui::Ui; | |
|
5 | use hg::operations::find_root; | |||
5 | use hg::operations::{ |
|
6 | use hg::operations::{ | |
6 |
|
|
7 | debug_data, DebugDataError, DebugDataErrorKind, DebugDataKind, | |
7 | }; |
|
8 | }; | |
8 | use micro_timer::timed; |
|
9 | use micro_timer::timed; | |
9 |
|
10 | |||
@@ -25,9 +26,9 b" impl<'a> DebugDataCommand<'a> {" | |||||
25 | impl<'a> Command for DebugDataCommand<'a> { |
|
26 | impl<'a> Command for DebugDataCommand<'a> { | |
26 | #[timed] |
|
27 | #[timed] | |
27 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { |
|
28 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
28 | let mut operation = DebugData::new(self.rev, self.kind); |
|
29 | let root = find_root()?; | |
29 | let data = |
|
30 | let data = debug_data(&root, self.rev, self.kind) | |
30 |
|
|
31 | .map_err(|e| to_command_error(self.rev, e))?; | |
31 |
|
32 | |||
32 | let mut stdout = ui.stdout_buffer(); |
|
33 | let mut stdout = ui.stdout_buffer(); | |
33 | stdout.write_all(&data)?; |
|
34 | stdout.write_all(&data)?; | |
@@ -40,7 +41,6 b" impl<'a> Command for DebugDataCommand<'a" | |||||
40 | /// Convert operation errors to command errors |
|
41 | /// Convert operation errors to command errors | |
41 | fn to_command_error(rev: &str, err: DebugDataError) -> CommandError { |
|
42 | fn to_command_error(rev: &str, err: DebugDataError) -> CommandError { | |
42 | match err.kind { |
|
43 | match err.kind { | |
43 | DebugDataErrorKind::FindRootError(err) => CommandError::from(err), |
|
|||
44 | DebugDataErrorKind::IoError(err) => CommandError { |
|
44 | DebugDataErrorKind::IoError(err) => CommandError { | |
45 | kind: CommandErrorKind::Abort(Some( |
|
45 | kind: CommandErrorKind::Abort(Some( | |
46 | utf8_to_local(&format!("abort: {}\n", err)).into(), |
|
46 | utf8_to_local(&format!("abort: {}\n", err)).into(), |
@@ -1,7 +1,7 b'' | |||||
1 | use crate::commands::Command; |
|
1 | use crate::commands::Command; | |
2 | use crate::error::CommandError; |
|
2 | use crate::error::CommandError; | |
3 | use crate::ui::Ui; |
|
3 | use crate::ui::Ui; | |
4 |
use hg::operations:: |
|
4 | use hg::operations::find_root; | |
5 | use hg::requirements; |
|
5 | use hg::requirements; | |
6 |
|
6 | |||
7 | pub const HELP_TEXT: &str = " |
|
7 | pub const HELP_TEXT: &str = " | |
@@ -18,7 +18,7 b' impl DebugRequirementsCommand {' | |||||
18 |
|
18 | |||
19 | impl Command for DebugRequirementsCommand { |
|
19 | impl Command for DebugRequirementsCommand { | |
20 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { |
|
20 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
21 |
let root = |
|
21 | let root = find_root()?; | |
22 | let mut output = String::new(); |
|
22 | let mut output = String::new(); | |
23 | for req in requirements::load(&root)? { |
|
23 | for req in requirements::load(&root)? { | |
24 | output.push_str(&req); |
|
24 | output.push_str(&req); |
@@ -2,14 +2,13 b' 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::utf8_to_local; | |
4 | use crate::ui::Ui; |
|
4 | use crate::ui::Ui; | |
5 |
use hg::operations:: |
|
5 | use hg::operations::find_root; | |
6 | use hg::operations::{ |
|
6 | use hg::operations::{ | |
7 |
|
|
7 | list_rev_tracked_files, ListRevTrackedFilesError, | |
8 |
List |
|
8 | ListRevTrackedFilesErrorKind, | |
9 | }; |
|
9 | }; | |
10 | use hg::operations::{ |
|
10 | use hg::operations::{ | |
11 | ListRevTrackedFiles, ListRevTrackedFilesError, |
|
11 | Dirstate, ListDirstateTrackedFilesError, ListDirstateTrackedFilesErrorKind, | |
12 | ListRevTrackedFilesErrorKind, |
|
|||
13 | }; |
|
12 | }; | |
14 | use hg::requirements; |
|
13 | use hg::requirements; | |
15 | use hg::utils::files::{get_bytes_from_path, relativize_path}; |
|
14 | use hg::utils::files::{get_bytes_from_path, relativize_path}; | |
@@ -57,17 +56,15 b" impl<'a> FilesCommand<'a> {" | |||||
57 |
|
56 | |||
58 | impl<'a> Command for FilesCommand<'a> { |
|
57 | impl<'a> Command for FilesCommand<'a> { | |
59 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { |
|
58 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
60 |
let root = |
|
59 | let root = find_root()?; | |
61 | requirements::check(&root)?; |
|
60 | requirements::check(&root)?; | |
62 | if let Some(rev) = self.rev { |
|
61 | if let Some(rev) = self.rev { | |
63 |
let |
|
62 | let files = list_rev_tracked_files(&root, rev) | |
64 | .map_err(|e| map_rev_error(rev, e))?; |
|
63 | .map_err(|e| map_rev_error(rev, e))?; | |
65 | let files = operation.run().map_err(|e| map_rev_error(rev, e))?; |
|
64 | self.display_files(ui, &root, files.iter()) | |
66 | self.display_files(ui, &root, files) |
|
|||
67 | } else { |
|
65 | } else { | |
68 | let mut operation = ListDirstateTrackedFiles::new(&root) |
|
66 | let distate = Dirstate::new(&root).map_err(map_dirstate_error)?; | |
69 |
|
|
67 | let files = distate.tracked_files().map_err(map_dirstate_error)?; | |
70 | let files = operation.run().map_err(map_dirstate_error)?; |
|
|||
71 | self.display_files(ui, &root, files) |
|
68 | self.display_files(ui, &root, files) | |
72 | } |
|
69 | } | |
73 | } |
|
70 | } |
@@ -2,7 +2,7 b' use crate::commands::Command;' | |||||
2 | use crate::error::CommandError; |
|
2 | use crate::error::CommandError; | |
3 | use crate::ui::Ui; |
|
3 | use crate::ui::Ui; | |
4 | use format_bytes::format_bytes; |
|
4 | use format_bytes::format_bytes; | |
5 |
use hg::operations:: |
|
5 | use hg::operations::find_root; | |
6 | use hg::utils::files::get_bytes_from_path; |
|
6 | use hg::utils::files::get_bytes_from_path; | |
7 |
|
7 | |||
8 | pub const HELP_TEXT: &str = " |
|
8 | pub const HELP_TEXT: &str = " | |
@@ -21,7 +21,7 b' impl RootCommand {' | |||||
21 |
|
21 | |||
22 | impl Command for RootCommand { |
|
22 | impl Command for RootCommand { | |
23 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { |
|
23 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
24 |
let path_buf = |
|
24 | let path_buf = find_root()?; | |
25 |
|
25 | |||
26 | let bytes = get_bytes_from_path(path_buf); |
|
26 | let bytes = get_bytes_from_path(path_buf); | |
27 |
|
27 |
General Comments 0
You need to be logged in to leave comments.
Login now