Show More
@@ -292,7 +292,7 b" pub struct DirstateStatus<'a> {" | |||||
292 | pub unsure: Vec<HgPathCow<'a>>, |
|
292 | pub unsure: Vec<HgPathCow<'a>>, | |
293 |
|
293 | |||
294 | /// Only filled if `collect_traversed_dirs` is `true` |
|
294 | /// Only filled if `collect_traversed_dirs` is `true` | |
295 |
pub traversed: Vec<HgPath |
|
295 | pub traversed: Vec<HgPathCow<'a>>, | |
296 | } |
|
296 | } | |
297 |
|
297 | |||
298 | #[derive(Debug, derive_more::From)] |
|
298 | #[derive(Debug, derive_more::From)] | |
@@ -880,7 +880,7 b' where' | |||||
880 | #[timed] |
|
880 | #[timed] | |
881 | pub fn build_response<'a>( |
|
881 | pub fn build_response<'a>( | |
882 | results: impl IntoIterator<Item = DispatchedPath<'a>>, |
|
882 | results: impl IntoIterator<Item = DispatchedPath<'a>>, | |
883 |
traversed: Vec<HgPath |
|
883 | traversed: Vec<HgPathCow<'a>>, | |
884 | ) -> DirstateStatus<'a> { |
|
884 | ) -> DirstateStatus<'a> { | |
885 | let mut unsure = vec![]; |
|
885 | let mut unsure = vec![]; | |
886 | let mut modified = vec![]; |
|
886 | let mut modified = vec![]; |
@@ -46,6 +46,13 b" pub struct DirstateMap<'on_disk> {" | |||||
46 | /// string prefix. |
|
46 | /// string prefix. | |
47 | pub(super) type NodeKey<'on_disk> = WithBasename<Cow<'on_disk, HgPath>>; |
|
47 | pub(super) type NodeKey<'on_disk> = WithBasename<Cow<'on_disk, HgPath>>; | |
48 |
|
48 | |||
|
49 | /// Similar to `&'tree Cow<'on_disk, HgPath>`, but can also be returned | |||
|
50 | /// for on-disk nodes that don’t actually have a `Cow` to borrow. | |||
|
51 | pub(super) enum BorrowedPath<'tree, 'on_disk> { | |||
|
52 | InMemory(&'tree HgPathBuf), | |||
|
53 | OnDisk(&'on_disk HgPath), | |||
|
54 | } | |||
|
55 | ||||
49 | pub(super) enum ChildNodes<'on_disk> { |
|
56 | pub(super) enum ChildNodes<'on_disk> { | |
50 | InMemory(FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>), |
|
57 | InMemory(FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>), | |
51 | OnDisk(&'on_disk [on_disk::Node]), |
|
58 | OnDisk(&'on_disk [on_disk::Node]), | |
@@ -61,6 +68,26 b" pub(super) enum NodeRef<'tree, 'on_disk>" | |||||
61 | OnDisk(&'on_disk on_disk::Node), |
|
68 | OnDisk(&'on_disk on_disk::Node), | |
62 | } |
|
69 | } | |
63 |
|
70 | |||
|
71 | impl<'tree, 'on_disk> BorrowedPath<'tree, 'on_disk> { | |||
|
72 | pub fn detach_from_tree(&self) -> Cow<'on_disk, HgPath> { | |||
|
73 | match *self { | |||
|
74 | BorrowedPath::InMemory(in_memory) => Cow::Owned(in_memory.clone()), | |||
|
75 | BorrowedPath::OnDisk(on_disk) => Cow::Borrowed(on_disk), | |||
|
76 | } | |||
|
77 | } | |||
|
78 | } | |||
|
79 | ||||
|
80 | impl<'tree, 'on_disk> std::ops::Deref for BorrowedPath<'tree, 'on_disk> { | |||
|
81 | type Target = HgPath; | |||
|
82 | ||||
|
83 | fn deref(&self) -> &HgPath { | |||
|
84 | match *self { | |||
|
85 | BorrowedPath::InMemory(in_memory) => in_memory, | |||
|
86 | BorrowedPath::OnDisk(on_disk) => on_disk, | |||
|
87 | } | |||
|
88 | } | |||
|
89 | } | |||
|
90 | ||||
64 | impl Default for ChildNodes<'_> { |
|
91 | impl Default for ChildNodes<'_> { | |
65 | fn default() -> Self { |
|
92 | fn default() -> Self { | |
66 | ChildNodes::InMemory(Default::default()) |
|
93 | ChildNodes::InMemory(Default::default()) | |
@@ -210,15 +237,19 b" impl<'tree, 'on_disk> NodeRef<'tree, 'on" | |||||
210 | } |
|
237 | } | |
211 | } |
|
238 | } | |
212 |
|
239 | |||
213 | /// Returns a `Cow` that can borrow 'on_disk but is detached from 'tree |
|
240 | /// Returns a `BorrowedPath`, which can be turned into a `Cow<'on_disk, | |
214 | pub(super) fn full_path_cow( |
|
241 | /// HgPath>` detached from `'tree` | |
|
242 | pub(super) fn full_path_borrowed( | |||
215 | &self, |
|
243 | &self, | |
216 | on_disk: &'on_disk [u8], |
|
244 | on_disk: &'on_disk [u8], | |
217 |
) -> Result< |
|
245 | ) -> Result<BorrowedPath<'tree, 'on_disk>, DirstateV2ParseError> { | |
218 | match self { |
|
246 | match self { | |
219 |
NodeRef::InMemory(path, _node) => |
|
247 | NodeRef::InMemory(path, _node) => match path.full_path() { | |
|
248 | Cow::Borrowed(on_disk) => Ok(BorrowedPath::OnDisk(on_disk)), | |||
|
249 | Cow::Owned(in_memory) => Ok(BorrowedPath::InMemory(in_memory)), | |||
|
250 | }, | |||
220 | NodeRef::OnDisk(node) => { |
|
251 | NodeRef::OnDisk(node) => { | |
221 |
Ok( |
|
252 | Ok(BorrowedPath::OnDisk(node.full_path(on_disk)?)) | |
222 | } |
|
253 | } | |
223 | } |
|
254 | } | |
224 | } |
|
255 | } | |
@@ -819,7 +850,10 b" impl<'on_disk> super::dispatch::Dirstate" | |||||
819 | node.copy_source(self.on_disk)?, |
|
850 | node.copy_source(self.on_disk)?, | |
820 | ); |
|
851 | ); | |
821 | if entry.mtime_is_ambiguous(now) { |
|
852 | if entry.mtime_is_ambiguous(now) { | |
822 |
ambiguous_mtimes.push( |
|
853 | ambiguous_mtimes.push( | |
|
854 | node.full_path_borrowed(self.on_disk)? | |||
|
855 | .detach_from_tree(), | |||
|
856 | ) | |||
823 | } |
|
857 | } | |
824 | } |
|
858 | } | |
825 | } |
|
859 | } | |
@@ -855,7 +889,10 b" impl<'on_disk> super::dispatch::Dirstate" | |||||
855 | let node = node?; |
|
889 | let node = node?; | |
856 | if let Some(entry) = node.entry()? { |
|
890 | if let Some(entry) = node.entry()? { | |
857 | if entry.mtime_is_ambiguous(now) { |
|
891 | if entry.mtime_is_ambiguous(now) { | |
858 |
paths.push( |
|
892 | paths.push( | |
|
893 | node.full_path_borrowed(self.on_disk)? | |||
|
894 | .detach_from_tree(), | |||
|
895 | ) | |||
859 | } |
|
896 | } | |
860 | } |
|
897 | } | |
861 | } |
|
898 | } |
@@ -1,4 +1,5 b'' | |||||
1 | use crate::dirstate::status::IgnoreFnType; |
|
1 | use crate::dirstate::status::IgnoreFnType; | |
|
2 | use crate::dirstate_tree::dirstate_map::BorrowedPath; | |||
2 | use crate::dirstate_tree::dirstate_map::ChildNodesRef; |
|
3 | use crate::dirstate_tree::dirstate_map::ChildNodesRef; | |
3 | use crate::dirstate_tree::dirstate_map::DirstateMap; |
|
4 | use crate::dirstate_tree::dirstate_map::DirstateMap; | |
4 | use crate::dirstate_tree::dirstate_map::NodeRef; |
|
5 | use crate::dirstate_tree::dirstate_map::NodeRef; | |
@@ -17,7 +18,6 b' use crate::StatusError;' | |||||
17 | use crate::StatusOptions; |
|
18 | use crate::StatusOptions; | |
18 | use micro_timer::timed; |
|
19 | use micro_timer::timed; | |
19 | use rayon::prelude::*; |
|
20 | use rayon::prelude::*; | |
20 | use std::borrow::Cow; |
|
|||
21 | use std::io; |
|
21 | use std::io; | |
22 | use std::path::Path; |
|
22 | use std::path::Path; | |
23 | use std::path::PathBuf; |
|
23 | use std::path::PathBuf; | |
@@ -39,7 +39,7 b" pub fn status<'tree, 'on_disk: 'tree>(" | |||||
39 | root_dir: PathBuf, |
|
39 | root_dir: PathBuf, | |
40 | ignore_files: Vec<PathBuf>, |
|
40 | ignore_files: Vec<PathBuf>, | |
41 | options: StatusOptions, |
|
41 | options: StatusOptions, | |
42 |
) -> Result<(DirstateStatus<' |
|
42 | ) -> Result<(DirstateStatus<'on_disk>, Vec<PatternFileWarning>), StatusError> { | |
43 | let (ignore_fn, warnings): (IgnoreFnType, _) = |
|
43 | let (ignore_fn, warnings): (IgnoreFnType, _) = | |
44 | if options.list_ignored || options.list_unknown { |
|
44 | if options.list_ignored || options.list_unknown { | |
45 | get_ignore_function(ignore_files, &root_dir)? |
|
45 | get_ignore_function(ignore_files, &root_dir)? | |
@@ -55,7 +55,7 b" pub fn status<'tree, 'on_disk: 'tree>(" | |||||
55 | outcome: Mutex::new(DirstateStatus::default()), |
|
55 | outcome: Mutex::new(DirstateStatus::default()), | |
56 | }; |
|
56 | }; | |
57 | let is_at_repo_root = true; |
|
57 | let is_at_repo_root = true; | |
58 | let hg_path = HgPath::new(""); |
|
58 | let hg_path = &BorrowedPath::OnDisk(HgPath::new("")); | |
59 | let has_ignored_ancestor = false; |
|
59 | let has_ignored_ancestor = false; | |
60 | common.traverse_fs_directory_and_dirstate( |
|
60 | common.traverse_fs_directory_and_dirstate( | |
61 | has_ignored_ancestor, |
|
61 | has_ignored_ancestor, | |
@@ -69,15 +69,15 b" pub fn status<'tree, 'on_disk: 'tree>(" | |||||
69 |
|
69 | |||
70 | /// Bag of random things needed by various parts of the algorithm. Reduces the |
|
70 | /// Bag of random things needed by various parts of the algorithm. Reduces the | |
71 | /// number of parameters passed to functions. |
|
71 | /// number of parameters passed to functions. | |
72 |
struct StatusCommon<' |
|
72 | struct StatusCommon<'a, 'tree, 'on_disk: 'tree> { | |
73 | dmap: &'tree DirstateMap<'on_disk>, |
|
73 | dmap: &'tree DirstateMap<'on_disk>, | |
74 | options: StatusOptions, |
|
74 | options: StatusOptions, | |
75 | matcher: &'a (dyn Matcher + Sync), |
|
75 | matcher: &'a (dyn Matcher + Sync), | |
76 | ignore_fn: IgnoreFnType<'a>, |
|
76 | ignore_fn: IgnoreFnType<'a>, | |
77 |
outcome: Mutex<DirstateStatus<' |
|
77 | outcome: Mutex<DirstateStatus<'on_disk>>, | |
78 | } |
|
78 | } | |
79 |
|
79 | |||
80 |
impl<'tree, ' |
|
80 | impl<'a, 'tree, 'on_disk> StatusCommon<'a, 'tree, 'on_disk> { | |
81 | fn read_dir( |
|
81 | fn read_dir( | |
82 | &self, |
|
82 | &self, | |
83 | hg_path: &HgPath, |
|
83 | hg_path: &HgPath, | |
@@ -100,8 +100,8 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
100 | fn traverse_fs_directory_and_dirstate( |
|
100 | fn traverse_fs_directory_and_dirstate( | |
101 | &self, |
|
101 | &self, | |
102 | has_ignored_ancestor: bool, |
|
102 | has_ignored_ancestor: bool, | |
103 | dirstate_nodes: ChildNodesRef<'tree, '_>, |
|
103 | dirstate_nodes: ChildNodesRef<'tree, 'on_disk>, | |
104 |
directory_hg_path: &'tree |
|
104 | directory_hg_path: &BorrowedPath<'tree, 'on_disk>, | |
105 | directory_fs_path: &Path, |
|
105 | directory_fs_path: &Path, | |
106 | is_at_repo_root: bool, |
|
106 | is_at_repo_root: bool, | |
107 | ) -> Result<(), DirstateV2ParseError> { |
|
107 | ) -> Result<(), DirstateV2ParseError> { | |
@@ -199,10 +199,10 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
199 | &self, |
|
199 | &self, | |
200 | fs_path: &Path, |
|
200 | fs_path: &Path, | |
201 | fs_metadata: &std::fs::Metadata, |
|
201 | fs_metadata: &std::fs::Metadata, | |
202 | dirstate_node: NodeRef<'tree, '_>, |
|
202 | dirstate_node: NodeRef<'tree, 'on_disk>, | |
203 | has_ignored_ancestor: bool, |
|
203 | has_ignored_ancestor: bool, | |
204 | ) -> Result<(), DirstateV2ParseError> { |
|
204 | ) -> Result<(), DirstateV2ParseError> { | |
205 | let hg_path = dirstate_node.full_path(self.dmap.on_disk)?; |
|
205 | let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?; | |
206 | let file_type = fs_metadata.file_type(); |
|
206 | let file_type = fs_metadata.file_type(); | |
207 | let file_or_symlink = file_type.is_file() || file_type.is_symlink(); |
|
207 | let file_or_symlink = file_type.is_file() || file_type.is_symlink(); | |
208 | if !file_or_symlink { |
|
208 | if !file_or_symlink { | |
@@ -210,13 +210,17 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
210 | // `hg rm` or similar) or deleted before it could be |
|
210 | // `hg rm` or similar) or deleted before it could be | |
211 | // replaced by a directory or something else. |
|
211 | // replaced by a directory or something else. | |
212 | self.mark_removed_or_deleted_if_file( |
|
212 | self.mark_removed_or_deleted_if_file( | |
213 | hg_path, |
|
213 | &hg_path, | |
214 | dirstate_node.state()?, |
|
214 | dirstate_node.state()?, | |
215 | ); |
|
215 | ); | |
216 | } |
|
216 | } | |
217 | if file_type.is_dir() { |
|
217 | if file_type.is_dir() { | |
218 | if self.options.collect_traversed_dirs { |
|
218 | if self.options.collect_traversed_dirs { | |
219 | self.outcome.lock().unwrap().traversed.push(hg_path.into()) |
|
219 | self.outcome | |
|
220 | .lock() | |||
|
221 | .unwrap() | |||
|
222 | .traversed | |||
|
223 | .push(hg_path.detach_from_tree()) | |||
220 | } |
|
224 | } | |
221 | let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path); |
|
225 | let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path); | |
222 | let is_at_repo_root = false; |
|
226 | let is_at_repo_root = false; | |
@@ -229,24 +233,26 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
229 | )? |
|
233 | )? | |
230 | } else { |
|
234 | } else { | |
231 | if file_or_symlink && self.matcher.matches(hg_path) { |
|
235 | if file_or_symlink && self.matcher.matches(hg_path) { | |
232 | let full_path = Cow::from(hg_path); |
|
|||
233 | if let Some(state) = dirstate_node.state()? { |
|
236 | if let Some(state) = dirstate_node.state()? { | |
234 | match state { |
|
237 | match state { | |
235 |
EntryState::Added => |
|
238 | EntryState::Added => self | |
236 |
|
|
239 | .outcome | |
237 |
|
|
240 | .lock() | |
|
241 | .unwrap() | |||
|
242 | .added | |||
|
243 | .push(hg_path.detach_from_tree()), | |||
238 | EntryState::Removed => self |
|
244 | EntryState::Removed => self | |
239 | .outcome |
|
245 | .outcome | |
240 | .lock() |
|
246 | .lock() | |
241 | .unwrap() |
|
247 | .unwrap() | |
242 | .removed |
|
248 | .removed | |
243 |
.push( |
|
249 | .push(hg_path.detach_from_tree()), | |
244 | EntryState::Merged => self |
|
250 | EntryState::Merged => self | |
245 | .outcome |
|
251 | .outcome | |
246 | .lock() |
|
252 | .lock() | |
247 | .unwrap() |
|
253 | .unwrap() | |
248 | .modified |
|
254 | .modified | |
249 |
.push( |
|
255 | .push(hg_path.detach_from_tree()), | |
250 | EntryState::Normal => self |
|
256 | EntryState::Normal => self | |
251 | .handle_normal_file(&dirstate_node, fs_metadata)?, |
|
257 | .handle_normal_file(&dirstate_node, fs_metadata)?, | |
252 | // This variant is not used in DirstateMap |
|
258 | // This variant is not used in DirstateMap | |
@@ -256,10 +262,7 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
256 | } else { |
|
262 | } else { | |
257 | // `node.entry.is_none()` indicates a "directory" |
|
263 | // `node.entry.is_none()` indicates a "directory" | |
258 | // node, but the filesystem has a file |
|
264 | // node, but the filesystem has a file | |
259 | self.mark_unknown_or_ignored( |
|
265 | self.mark_unknown_or_ignored(has_ignored_ancestor, hg_path) | |
260 | has_ignored_ancestor, |
|
|||
261 | full_path, |
|
|||
262 | ) |
|
|||
263 | } |
|
266 | } | |
264 | } |
|
267 | } | |
265 |
|
268 | |||
@@ -275,7 +278,7 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
275 | /// filesystem |
|
278 | /// filesystem | |
276 | fn handle_normal_file( |
|
279 | fn handle_normal_file( | |
277 | &self, |
|
280 | &self, | |
278 | dirstate_node: &NodeRef<'tree, '_>, |
|
281 | dirstate_node: &NodeRef<'tree, 'on_disk>, | |
279 | fs_metadata: &std::fs::Metadata, |
|
282 | fs_metadata: &std::fs::Metadata, | |
280 | ) -> Result<(), DirstateV2ParseError> { |
|
283 | ) -> Result<(), DirstateV2ParseError> { | |
281 | // Keep the low 31 bits |
|
284 | // Keep the low 31 bits | |
@@ -289,7 +292,7 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
289 | let entry = dirstate_node |
|
292 | let entry = dirstate_node | |
290 | .entry()? |
|
293 | .entry()? | |
291 | .expect("handle_normal_file called with entry-less node"); |
|
294 | .expect("handle_normal_file called with entry-less node"); | |
292 |
let |
|
295 | let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?; | |
293 | let mode_changed = |
|
296 | let mode_changed = | |
294 | || self.options.check_exec && entry.mode_changed(fs_metadata); |
|
297 | || self.options.check_exec && entry.mode_changed(fs_metadata); | |
295 | let size_changed = entry.size != truncate_u64(fs_metadata.len()); |
|
298 | let size_changed = entry.size != truncate_u64(fs_metadata.len()); | |
@@ -299,20 +302,36 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
299 | { |
|
302 | { | |
300 | // issue6456: Size returned may be longer due to encryption |
|
303 | // issue6456: Size returned may be longer due to encryption | |
301 | // on EXT-4 fscrypt. TODO maybe only do it on EXT4? |
|
304 | // on EXT-4 fscrypt. TODO maybe only do it on EXT4? | |
302 | self.outcome.lock().unwrap().unsure.push(full_path) |
|
305 | self.outcome | |
|
306 | .lock() | |||
|
307 | .unwrap() | |||
|
308 | .unsure | |||
|
309 | .push(hg_path.detach_from_tree()) | |||
303 | } else if dirstate_node.has_copy_source() |
|
310 | } else if dirstate_node.has_copy_source() | |
304 | || entry.is_from_other_parent() |
|
311 | || entry.is_from_other_parent() | |
305 | || (entry.size >= 0 && (size_changed || mode_changed())) |
|
312 | || (entry.size >= 0 && (size_changed || mode_changed())) | |
306 | { |
|
313 | { | |
307 | self.outcome.lock().unwrap().modified.push(full_path) |
|
314 | self.outcome | |
|
315 | .lock() | |||
|
316 | .unwrap() | |||
|
317 | .modified | |||
|
318 | .push(hg_path.detach_from_tree()) | |||
308 | } else { |
|
319 | } else { | |
309 | let mtime = mtime_seconds(fs_metadata); |
|
320 | let mtime = mtime_seconds(fs_metadata); | |
310 | if truncate_i64(mtime) != entry.mtime |
|
321 | if truncate_i64(mtime) != entry.mtime | |
311 | || mtime == self.options.last_normal_time |
|
322 | || mtime == self.options.last_normal_time | |
312 | { |
|
323 | { | |
313 | self.outcome.lock().unwrap().unsure.push(full_path) |
|
324 | self.outcome | |
|
325 | .lock() | |||
|
326 | .unwrap() | |||
|
327 | .unsure | |||
|
328 | .push(hg_path.detach_from_tree()) | |||
314 | } else if self.options.list_clean { |
|
329 | } else if self.options.list_clean { | |
315 | self.outcome.lock().unwrap().clean.push(full_path) |
|
330 | self.outcome | |
|
331 | .lock() | |||
|
332 | .unwrap() | |||
|
333 | .clean | |||
|
334 | .push(hg_path.detach_from_tree()) | |||
316 | } |
|
335 | } | |
317 | } |
|
336 | } | |
318 | Ok(()) |
|
337 | Ok(()) | |
@@ -321,10 +340,10 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
321 | /// A node in the dirstate tree has no corresponding filesystem entry |
|
340 | /// A node in the dirstate tree has no corresponding filesystem entry | |
322 | fn traverse_dirstate_only( |
|
341 | fn traverse_dirstate_only( | |
323 | &self, |
|
342 | &self, | |
324 | dirstate_node: NodeRef<'tree, '_>, |
|
343 | dirstate_node: NodeRef<'tree, 'on_disk>, | |
325 | ) -> Result<(), DirstateV2ParseError> { |
|
344 | ) -> Result<(), DirstateV2ParseError> { | |
326 | self.mark_removed_or_deleted_if_file( |
|
345 | self.mark_removed_or_deleted_if_file( | |
327 | dirstate_node.full_path(self.dmap.on_disk)?, |
|
346 | &dirstate_node.full_path_borrowed(self.dmap.on_disk)?, | |
328 | dirstate_node.state()?, |
|
347 | dirstate_node.state()?, | |
329 | ); |
|
348 | ); | |
330 | dirstate_node |
|
349 | dirstate_node | |
@@ -340,15 +359,23 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
340 | /// Does nothing on a "directory" node |
|
359 | /// Does nothing on a "directory" node | |
341 | fn mark_removed_or_deleted_if_file( |
|
360 | fn mark_removed_or_deleted_if_file( | |
342 | &self, |
|
361 | &self, | |
343 |
hg_path: &'tree |
|
362 | hg_path: &BorrowedPath<'tree, 'on_disk>, | |
344 | dirstate_node_state: Option<EntryState>, |
|
363 | dirstate_node_state: Option<EntryState>, | |
345 | ) { |
|
364 | ) { | |
346 | if let Some(state) = dirstate_node_state { |
|
365 | if let Some(state) = dirstate_node_state { | |
347 | if self.matcher.matches(hg_path) { |
|
366 | if self.matcher.matches(hg_path) { | |
348 | if let EntryState::Removed = state { |
|
367 | if let EntryState::Removed = state { | |
349 | self.outcome.lock().unwrap().removed.push(hg_path.into()) |
|
368 | self.outcome | |
|
369 | .lock() | |||
|
370 | .unwrap() | |||
|
371 | .removed | |||
|
372 | .push(hg_path.detach_from_tree()) | |||
350 | } else { |
|
373 | } else { | |
351 | self.outcome.lock().unwrap().deleted.push(hg_path.into()) |
|
374 | self.outcome | |
|
375 | .lock() | |||
|
376 | .unwrap() | |||
|
377 | .deleted | |||
|
378 | .push(hg_path.detach_from_tree()) | |||
352 | } |
|
379 | } | |
353 | } |
|
380 | } | |
354 | } |
|
381 | } | |
@@ -395,23 +422,34 b" impl<'tree, 'a> StatusCommon<'tree, 'a, " | |||||
395 | self.outcome.lock().unwrap().traversed.push(hg_path.into()) |
|
422 | self.outcome.lock().unwrap().traversed.push(hg_path.into()) | |
396 | } |
|
423 | } | |
397 | } else if file_or_symlink && self.matcher.matches(&hg_path) { |
|
424 | } else if file_or_symlink && self.matcher.matches(&hg_path) { | |
398 |
self.mark_unknown_or_ignored( |
|
425 | self.mark_unknown_or_ignored( | |
|
426 | has_ignored_ancestor, | |||
|
427 | &BorrowedPath::InMemory(&hg_path), | |||
|
428 | ) | |||
399 | } |
|
429 | } | |
400 | } |
|
430 | } | |
401 |
|
431 | |||
402 | fn mark_unknown_or_ignored( |
|
432 | fn mark_unknown_or_ignored( | |
403 | &self, |
|
433 | &self, | |
404 | has_ignored_ancestor: bool, |
|
434 | has_ignored_ancestor: bool, | |
405 |
hg_path: |
|
435 | hg_path: &BorrowedPath<'_, 'on_disk>, | |
406 | ) { |
|
436 | ) { | |
407 | let is_ignored = has_ignored_ancestor || (self.ignore_fn)(&hg_path); |
|
437 | let is_ignored = has_ignored_ancestor || (self.ignore_fn)(&hg_path); | |
408 | if is_ignored { |
|
438 | if is_ignored { | |
409 | if self.options.list_ignored { |
|
439 | if self.options.list_ignored { | |
410 | self.outcome.lock().unwrap().ignored.push(hg_path) |
|
440 | self.outcome | |
|
441 | .lock() | |||
|
442 | .unwrap() | |||
|
443 | .ignored | |||
|
444 | .push(hg_path.detach_from_tree()) | |||
411 | } |
|
445 | } | |
412 | } else { |
|
446 | } else { | |
413 | if self.options.list_unknown { |
|
447 | if self.options.list_unknown { | |
414 | self.outcome.lock().unwrap().unknown.push(hg_path) |
|
448 | self.outcome | |
|
449 | .lock() | |||
|
450 | .unwrap() | |||
|
451 | .unknown | |||
|
452 | .push(hg_path.detach_from_tree()) | |||
415 | } |
|
453 | } | |
416 | } |
|
454 | } | |
417 | } |
|
455 | } |
@@ -61,7 +61,10 b" impl<'a, M: ?Sized + Matcher + Sync> Sta" | |||||
61 | } |
|
61 | } | |
62 |
|
62 | |||
63 | drop(traversed_sender); |
|
63 | drop(traversed_sender); | |
64 |
let traversed = traversed_receiver |
|
64 | let traversed = traversed_receiver | |
|
65 | .into_iter() | |||
|
66 | .map(std::borrow::Cow::Owned) | |||
|
67 | .collect(); | |||
65 |
|
68 | |||
66 | Ok(build_response(results, traversed)) |
|
69 | Ok(build_response(results, traversed)) | |
67 | } |
|
70 | } |
General Comments 0
You need to be logged in to leave comments.
Login now