##// END OF EJS Templates
rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait...
Raphaël Gomès -
r44367:8c778261 default
parent child Browse files
Show More
@@ -11,6 +11,7 b''
11
11
12 use crate::{
12 use crate::{
13 dirstate::SIZE_FROM_OTHER_PARENT,
13 dirstate::SIZE_FROM_OTHER_PARENT,
14 matchers::Matcher,
14 utils::{
15 utils::{
15 files::HgMetadata,
16 files::HgMetadata,
16 hg_path::{hg_path_to_path_buf, HgPath},
17 hg_path::{hg_path_to_path_buf, HgPath},
@@ -18,6 +19,7 b' use crate::{'
18 CopyMap, DirstateEntry, DirstateMap, EntryState,
19 CopyMap, DirstateEntry, DirstateMap, EntryState,
19 };
20 };
20 use rayon::prelude::*;
21 use rayon::prelude::*;
22 use std::collections::HashSet;
21 use std::path::Path;
23 use std::path::Path;
22
24
23 /// Marker enum used to dispatch new status entries into the right collections.
25 /// Marker enum used to dispatch new status entries into the right collections.
@@ -33,6 +35,8 b' enum Dispatch {'
33 Unknown,
35 Unknown,
34 }
36 }
35
37
38 type IoResult<T> = std::io::Result<T>;
39
36 /// Dates and times that are outside the 31-bit signed range are compared
40 /// Dates and times that are outside the 31-bit signed range are compared
37 /// modulo 2^31. This should prevent hg from behaving badly with very large
41 /// modulo 2^31. This should prevent hg from behaving badly with very large
38 /// files or corrupt dates while still having a high probability of detecting
42 /// files or corrupt dates while still having a high probability of detecting
@@ -116,6 +120,63 b' fn dispatch_missing(state: EntryState) -'
116 }
120 }
117 }
121 }
118
122
123 /// Get stat data about the files explicitly specified by match.
124 /// TODO subrepos
125 fn walk_explicit<'a>(
126 files: &'a HashSet<&HgPath>,
127 dmap: &'a DirstateMap,
128 root_dir: impl AsRef<Path> + Sync + Send,
129 check_exec: bool,
130 list_clean: bool,
131 last_normal_time: i64,
132 ) -> impl ParallelIterator<Item = IoResult<(&'a HgPath, Dispatch)>> {
133 files.par_iter().filter_map(move |filename| {
134 // TODO normalization
135 let normalized = filename.as_ref();
136
137 let buf = match hg_path_to_path_buf(normalized) {
138 Ok(x) => x,
139 Err(e) => return Some(Err(e.into())),
140 };
141 let target = root_dir.as_ref().join(buf);
142 let st = target.symlink_metadata();
143 match st {
144 Ok(meta) => {
145 let file_type = meta.file_type();
146 if file_type.is_file() || file_type.is_symlink() {
147 if let Some(entry) = dmap.get(normalized) {
148 return Some(Ok((
149 normalized,
150 dispatch_found(
151 &normalized,
152 *entry,
153 HgMetadata::from_metadata(meta),
154 &dmap.copy_map,
155 check_exec,
156 list_clean,
157 last_normal_time,
158 ),
159 )));
160 }
161 } else {
162 if dmap.contains_key(normalized) {
163 return Some(Ok((normalized, Dispatch::Removed)));
164 }
165 }
166 }
167 Err(_) => {
168 if let Some(entry) = dmap.get(normalized) {
169 return Some(Ok((
170 normalized,
171 dispatch_missing(entry.state),
172 )));
173 }
174 }
175 };
176 None
177 })
178 }
179
119 /// Stat all entries in the `DirstateMap` and mark them for dispatch into
180 /// Stat all entries in the `DirstateMap` and mark them for dispatch into
120 /// the relevant collections.
181 /// the relevant collections.
121 fn stat_dmap_entries(
182 fn stat_dmap_entries(
@@ -124,7 +185,7 b' fn stat_dmap_entries('
124 check_exec: bool,
185 check_exec: bool,
125 list_clean: bool,
186 list_clean: bool,
126 last_normal_time: i64,
187 last_normal_time: i64,
127 ) -> impl ParallelIterator<Item = std::io::Result<(&HgPath, Dispatch)>> {
188 ) -> impl ParallelIterator<Item = IoResult<(&HgPath, Dispatch)>> {
128 dmap.par_iter().map(move |(filename, entry)| {
189 dmap.par_iter().map(move |(filename, entry)| {
129 let filename: &HgPath = filename;
190 let filename: &HgPath = filename;
130 let filename_as_path = hg_path_to_path_buf(filename)?;
191 let filename_as_path = hg_path_to_path_buf(filename)?;
@@ -174,9 +235,9 b" pub struct StatusResult<'a> {"
174 * TODO unknown */
235 * TODO unknown */
175 }
236 }
176
237
177 fn build_response(
238 fn build_response<'a>(
178 results: Vec<(&HgPath, Dispatch)>,
239 results: impl IntoIterator<Item = IoResult<(&'a HgPath, Dispatch)>>,
179 ) -> (Vec<&HgPath>, StatusResult) {
240 ) -> IoResult<(Vec<&'a HgPath>, StatusResult<'a>)> {
180 let mut lookup = vec![];
241 let mut lookup = vec![];
181 let mut modified = vec![];
242 let mut modified = vec![];
182 let mut added = vec![];
243 let mut added = vec![];
@@ -184,7 +245,8 b' fn build_response('
184 let mut deleted = vec![];
245 let mut deleted = vec![];
185 let mut clean = vec![];
246 let mut clean = vec![];
186
247
187 for (filename, dispatch) in results.into_iter() {
248 for res in results.into_iter() {
249 let (filename, dispatch) = res?;
188 match dispatch {
250 match dispatch {
189 Dispatch::Unknown => {}
251 Dispatch::Unknown => {}
190 Dispatch::Unsure => lookup.push(filename),
252 Dispatch::Unsure => lookup.push(filename),
@@ -196,7 +258,7 b' fn build_response('
196 }
258 }
197 }
259 }
198
260
199 (
261 Ok((
200 lookup,
262 lookup,
201 StatusResult {
263 StatusResult {
202 modified,
264 modified,
@@ -205,24 +267,40 b' fn build_response('
205 deleted,
267 deleted,
206 clean,
268 clean,
207 },
269 },
208 )
270 ))
209 }
271 }
210
272
211 pub fn status(
273 pub fn status<'a: 'c, 'b: 'c, 'c>(
212 dmap: &DirstateMap,
274 dmap: &'a DirstateMap,
275 matcher: &'b (impl Matcher),
213 root_dir: impl AsRef<Path> + Sync + Send + Copy,
276 root_dir: impl AsRef<Path> + Sync + Send + Copy,
214 list_clean: bool,
277 list_clean: bool,
215 last_normal_time: i64,
278 last_normal_time: i64,
216 check_exec: bool,
279 check_exec: bool,
217 ) -> std::io::Result<(Vec<&HgPath>, StatusResult)> {
280 ) -> IoResult<(Vec<&'c HgPath>, StatusResult<'c>)> {
218 let results: std::io::Result<_> = stat_dmap_entries(
281 let files = matcher.file_set();
219 &dmap,
282 let mut results = vec![];
220 root_dir,
283 if let Some(files) = files {
221 check_exec,
284 results.par_extend(walk_explicit(
222 list_clean,
285 &files,
223 last_normal_time,
286 &dmap,
224 )
287 root_dir,
225 .collect();
288 check_exec,
289 list_clean,
290 last_normal_time,
291 ));
292 }
226
293
227 Ok(build_response(results?))
294 if !matcher.is_exact() {
295 let stat_results = stat_dmap_entries(
296 &dmap,
297 root_dir,
298 check_exec,
299 list_clean,
300 last_normal_time,
301 );
302 results.par_extend(stat_results);
303 }
304
305 build_response(results)
228 }
306 }
@@ -17,6 +17,7 b' use cpython::{'
17 };
17 };
18 use hg::utils::files::get_path_from_bytes;
18 use hg::utils::files::get_path_from_bytes;
19
19
20 use hg::matchers::AlwaysMatcher;
20 use hg::status;
21 use hg::status;
21 use hg::utils::hg_path::HgPath;
22 use hg::utils::hg_path::HgPath;
22
23
@@ -53,9 +54,19 b' pub fn status_wrapper('
53 let dmap: DirstateMap = dmap.to_py_object(py);
54 let dmap: DirstateMap = dmap.to_py_object(py);
54 let dmap = dmap.get_inner(py);
55 let dmap = dmap.get_inner(py);
55
56
56 let (lookup, status_res) =
57 // TODO removed in the next patch to get the code to compile. This patch
57 status(&dmap, &root_dir, list_clean, last_normal_time, check_exec)
58 // is part of a series and does not make real sense on its own.
58 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
59 let matcher = AlwaysMatcher;
60
61 let (lookup, status_res) = status(
62 &dmap,
63 &matcher,
64 &root_dir,
65 list_clean,
66 last_normal_time,
67 check_exec,
68 )
69 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
59
70
60 let modified = collect_pybytes_list(py, status_res.modified.as_ref());
71 let modified = collect_pybytes_list(py, status_res.modified.as_ref());
61 let added = collect_pybytes_list(py, status_res.added.as_ref());
72 let added = collect_pybytes_list(py, status_res.added.as_ref());
General Comments 0
You need to be logged in to leave comments. Login now