##// 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 12 use crate::{
13 13 dirstate::SIZE_FROM_OTHER_PARENT,
14 matchers::Matcher,
14 15 utils::{
15 16 files::HgMetadata,
16 17 hg_path::{hg_path_to_path_buf, HgPath},
@@ -18,6 +19,7 b' use crate::{'
18 19 CopyMap, DirstateEntry, DirstateMap, EntryState,
19 20 };
20 21 use rayon::prelude::*;
22 use std::collections::HashSet;
21 23 use std::path::Path;
22 24
23 25 /// Marker enum used to dispatch new status entries into the right collections.
@@ -33,6 +35,8 b' enum Dispatch {'
33 35 Unknown,
34 36 }
35 37
38 type IoResult<T> = std::io::Result<T>;
39
36 40 /// Dates and times that are outside the 31-bit signed range are compared
37 41 /// modulo 2^31. This should prevent hg from behaving badly with very large
38 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 180 /// Stat all entries in the `DirstateMap` and mark them for dispatch into
120 181 /// the relevant collections.
121 182 fn stat_dmap_entries(
@@ -124,7 +185,7 b' fn stat_dmap_entries('
124 185 check_exec: bool,
125 186 list_clean: bool,
126 187 last_normal_time: i64,
127 ) -> impl ParallelIterator<Item = std::io::Result<(&HgPath, Dispatch)>> {
188 ) -> impl ParallelIterator<Item = IoResult<(&HgPath, Dispatch)>> {
128 189 dmap.par_iter().map(move |(filename, entry)| {
129 190 let filename: &HgPath = filename;
130 191 let filename_as_path = hg_path_to_path_buf(filename)?;
@@ -174,9 +235,9 b" pub struct StatusResult<'a> {"
174 235 * TODO unknown */
175 236 }
176 237
177 fn build_response(
178 results: Vec<(&HgPath, Dispatch)>,
179 ) -> (Vec<&HgPath>, StatusResult) {
238 fn build_response<'a>(
239 results: impl IntoIterator<Item = IoResult<(&'a HgPath, Dispatch)>>,
240 ) -> IoResult<(Vec<&'a HgPath>, StatusResult<'a>)> {
180 241 let mut lookup = vec![];
181 242 let mut modified = vec![];
182 243 let mut added = vec![];
@@ -184,7 +245,8 b' fn build_response('
184 245 let mut deleted = vec![];
185 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 250 match dispatch {
189 251 Dispatch::Unknown => {}
190 252 Dispatch::Unsure => lookup.push(filename),
@@ -196,7 +258,7 b' fn build_response('
196 258 }
197 259 }
198 260
199 (
261 Ok((
200 262 lookup,
201 263 StatusResult {
202 264 modified,
@@ -205,24 +267,40 b' fn build_response('
205 267 deleted,
206 268 clean,
207 269 },
208 )
270 ))
209 271 }
210 272
211 pub fn status(
212 dmap: &DirstateMap,
273 pub fn status<'a: 'c, 'b: 'c, 'c>(
274 dmap: &'a DirstateMap,
275 matcher: &'b (impl Matcher),
213 276 root_dir: impl AsRef<Path> + Sync + Send + Copy,
214 277 list_clean: bool,
215 278 last_normal_time: i64,
216 279 check_exec: bool,
217 ) -> std::io::Result<(Vec<&HgPath>, StatusResult)> {
218 let results: std::io::Result<_> = stat_dmap_entries(
219 &dmap,
220 root_dir,
221 check_exec,
222 list_clean,
223 last_normal_time,
224 )
225 .collect();
280 ) -> IoResult<(Vec<&'c HgPath>, StatusResult<'c>)> {
281 let files = matcher.file_set();
282 let mut results = vec![];
283 if let Some(files) = files {
284 results.par_extend(walk_explicit(
285 &files,
286 &dmap,
287 root_dir,
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 18 use hg::utils::files::get_path_from_bytes;
19 19
20 use hg::matchers::AlwaysMatcher;
20 21 use hg::status;
21 22 use hg::utils::hg_path::HgPath;
22 23
@@ -53,9 +54,19 b' pub fn status_wrapper('
53 54 let dmap: DirstateMap = dmap.to_py_object(py);
54 55 let dmap = dmap.get_inner(py);
55 56
56 let (lookup, status_res) =
57 status(&dmap, &root_dir, list_clean, last_normal_time, check_exec)
58 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
57 // TODO removed in the next patch to get the code to compile. This patch
58 // is part of a series and does not make real sense on its own.
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 71 let modified = collect_pybytes_list(py, status_res.modified.as_ref());
61 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