Mercurial > hg
comparison rust/hg-core/src/operations/list_tracked_files.rs @ 45536:639f33f22faf
hg-core: add a `ListRevTrackedFiles` operation
List files tracked at a given revision.
Differential Revision: https://phab.mercurial-scm.org/D9014
author | Antoine Cezar <antoine.cezar@octobus.net> |
---|---|
date | Fri, 18 Sep 2020 16:52:16 +0200 |
parents | 72b7d58d6e35 |
children | be951ca95b08 |
comparison
equal
deleted
inserted
replaced
45535:72b7d58d6e35 | 45536:639f33f22faf |
---|---|
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 crate::dirstate::parsers::parse_dirstate; | 8 use crate::dirstate::parsers::parse_dirstate; |
9 use crate::revlog::changelog::Changelog; | |
10 use crate::revlog::manifest::{Manifest, ManifestEntry}; | |
11 use crate::revlog::revlog::RevlogError; | |
12 use crate::revlog::Revision; | |
9 use crate::utils::hg_path::HgPath; | 13 use crate::utils::hg_path::HgPath; |
10 use crate::{DirstateParseError, EntryState}; | 14 use crate::{DirstateParseError, EntryState}; |
11 use rayon::prelude::*; | 15 use rayon::prelude::*; |
12 use std::convert::From; | 16 use std::convert::From; |
13 use std::fmt; | |
14 use std::fs; | 17 use std::fs; |
15 use std::ops::Deref; | 18 use std::path::PathBuf; |
16 use std::path::{Path, PathBuf}; | |
17 | 19 |
18 /// Kind of error encountered by `ListDirstateTrackedFiles` | 20 /// Kind of error encountered by `ListDirstateTrackedFiles` |
19 #[derive(Debug)] | 21 #[derive(Debug)] |
20 pub enum ListDirstateTrackedFilesErrorKind { | 22 pub enum ListDirstateTrackedFilesErrorKind { |
21 /// Error when reading the `dirstate` file | 23 /// Error when reading the `dirstate` file |
27 /// A `ListDirstateTrackedFiles` error | 29 /// A `ListDirstateTrackedFiles` error |
28 #[derive(Debug)] | 30 #[derive(Debug)] |
29 pub struct ListDirstateTrackedFilesError { | 31 pub struct ListDirstateTrackedFilesError { |
30 /// Kind of error encountered by `ListDirstateTrackedFiles` | 32 /// Kind of error encountered by `ListDirstateTrackedFiles` |
31 pub kind: ListDirstateTrackedFilesErrorKind, | 33 pub kind: ListDirstateTrackedFilesErrorKind, |
32 } | |
33 | |
34 impl std::error::Error for ListDirstateTrackedFilesError {} | |
35 | |
36 impl fmt::Display for ListDirstateTrackedFilesError { | |
37 fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
38 unimplemented!() | |
39 } | |
40 } | 34 } |
41 | 35 |
42 impl From<ListDirstateTrackedFilesErrorKind> | 36 impl From<ListDirstateTrackedFilesErrorKind> |
43 for ListDirstateTrackedFilesError | 37 for ListDirstateTrackedFilesError |
44 { | 38 { |
82 .collect(); | 76 .collect(); |
83 files.par_sort_unstable(); | 77 files.par_sort_unstable(); |
84 Ok(files) | 78 Ok(files) |
85 } | 79 } |
86 } | 80 } |
81 | |
82 /// Kind of error encountered by `ListRevTrackedFiles` | |
83 #[derive(Debug)] | |
84 pub enum ListRevTrackedFilesErrorKind { | |
85 /// Error when reading a `revlog` file. | |
86 IoError(std::io::Error), | |
87 /// The revision has not been found. | |
88 InvalidRevision, | |
89 /// A `revlog` file is corrupted. | |
90 CorruptedRevlog, | |
91 /// The `revlog` format version is not supported. | |
92 UnsuportedRevlogVersion(u16), | |
93 /// The `revlog` data format is not supported. | |
94 UnknowRevlogDataFormat(u8), | |
95 } | |
96 | |
97 /// A `ListRevTrackedFiles` error | |
98 #[derive(Debug)] | |
99 pub struct ListRevTrackedFilesError { | |
100 /// Kind of error encountered by `ListRevTrackedFiles` | |
101 pub kind: ListRevTrackedFilesErrorKind, | |
102 } | |
103 | |
104 impl From<ListRevTrackedFilesErrorKind> for ListRevTrackedFilesError { | |
105 fn from(kind: ListRevTrackedFilesErrorKind) -> Self { | |
106 ListRevTrackedFilesError { kind } | |
107 } | |
108 } | |
109 | |
110 impl From<RevlogError> for ListRevTrackedFilesError { | |
111 fn from(err: RevlogError) -> Self { | |
112 match err { | |
113 RevlogError::IoError(err) => { | |
114 ListRevTrackedFilesErrorKind::IoError(err) | |
115 } | |
116 RevlogError::UnsuportedVersion(version) => { | |
117 ListRevTrackedFilesErrorKind::UnsuportedRevlogVersion(version) | |
118 } | |
119 RevlogError::InvalidRevision => { | |
120 ListRevTrackedFilesErrorKind::InvalidRevision | |
121 } | |
122 RevlogError::Corrupted => { | |
123 ListRevTrackedFilesErrorKind::CorruptedRevlog | |
124 } | |
125 RevlogError::UnknowDataFormat(format) => { | |
126 ListRevTrackedFilesErrorKind::UnknowRevlogDataFormat(format) | |
127 } | |
128 } | |
129 .into() | |
130 } | |
131 } | |
132 | |
133 /// List files under Mercurial control at a given revision. | |
134 pub struct ListRevTrackedFiles<'a> { | |
135 /// The revision to list the files from. | |
136 rev: &'a str, | |
137 /// The changelog file | |
138 changelog: Changelog, | |
139 /// The manifest file | |
140 manifest: Manifest, | |
141 /// The manifest entry corresponding to the revision. | |
142 /// | |
143 /// Used to hold the owner of the returned references. | |
144 manifest_entry: Option<ManifestEntry>, | |
145 } | |
146 | |
147 impl<'a> ListRevTrackedFiles<'a> { | |
148 pub fn new( | |
149 root: &PathBuf, | |
150 rev: &'a str, | |
151 ) -> Result<Self, ListRevTrackedFilesError> { | |
152 let changelog = Changelog::open(&root)?; | |
153 let manifest = Manifest::open(&root)?; | |
154 | |
155 Ok(Self { | |
156 rev, | |
157 changelog, | |
158 manifest, | |
159 manifest_entry: None, | |
160 }) | |
161 } | |
162 | |
163 pub fn run( | |
164 &mut self, | |
165 ) -> Result<impl Iterator<Item = &HgPath>, ListRevTrackedFilesError> { | |
166 let changelog_entry = match self.rev.parse::<Revision>() { | |
167 Ok(rev) => self.changelog.get_rev(rev)?, | |
168 _ => { | |
169 let changelog_node = hex::decode(&self.rev).map_err(|_| { | |
170 ListRevTrackedFilesErrorKind::InvalidRevision | |
171 })?; | |
172 self.changelog.get_node(&changelog_node)? | |
173 } | |
174 }; | |
175 let manifest_node = hex::decode(&changelog_entry.manifest_node()?) | |
176 .map_err(|_| ListRevTrackedFilesErrorKind::CorruptedRevlog)?; | |
177 | |
178 self.manifest_entry = Some(self.manifest.get_node(&manifest_node)?); | |
179 | |
180 if let Some(ref manifest_entry) = self.manifest_entry { | |
181 Ok(manifest_entry.files()) | |
182 } else { | |
183 panic!( | |
184 "manifest entry should have been stored in self.manifest_node to ensure its lifetime since references are returned from it" | |
185 ) | |
186 } | |
187 } | |
188 } |