Mercurial > hg
comparison rust/hg-core/src/dirstate_tree/status.rs @ 47115:1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Errors such as insufficient permissions when listing a directory are logged,
and the algorithm continues without considering that directory.
Differential Revision: https://phab.mercurial-scm.org/D10549
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Mon, 26 Apr 2021 19:28:56 +0200 |
parents | aeb03758f37a |
children | 60d852ae7e7b |
comparison
equal
deleted
inserted
replaced
47114:aeb03758f37a | 47115:1b4f0f819f92 |
---|---|
4 use crate::dirstate_tree::dirstate_map::Node; | 4 use crate::dirstate_tree::dirstate_map::Node; |
5 use crate::matchers::get_ignore_function; | 5 use crate::matchers::get_ignore_function; |
6 use crate::matchers::Matcher; | 6 use crate::matchers::Matcher; |
7 use crate::utils::files::get_bytes_from_os_string; | 7 use crate::utils::files::get_bytes_from_os_string; |
8 use crate::utils::hg_path::HgPath; | 8 use crate::utils::hg_path::HgPath; |
9 use crate::BadMatch; | |
9 use crate::DirstateStatus; | 10 use crate::DirstateStatus; |
10 use crate::EntryState; | 11 use crate::EntryState; |
11 use crate::HgPathBuf; | 12 use crate::HgPathBuf; |
12 use crate::PatternFileWarning; | 13 use crate::PatternFileWarning; |
13 use crate::StatusError; | 14 use crate::StatusError; |
67 ignore_fn: IgnoreFnType<'a>, | 68 ignore_fn: IgnoreFnType<'a>, |
68 outcome: DirstateStatus<'tree>, | 69 outcome: DirstateStatus<'tree>, |
69 } | 70 } |
70 | 71 |
71 impl<'tree, 'a> StatusCommon<'tree, 'a> { | 72 impl<'tree, 'a> StatusCommon<'tree, 'a> { |
73 fn read_dir( | |
74 &mut self, | |
75 hg_path: &HgPath, | |
76 fs_path: &Path, | |
77 is_at_repo_root: bool, | |
78 ) -> Result<Vec<DirEntry>, ()> { | |
79 DirEntry::read_dir(fs_path, is_at_repo_root).map_err(|error| { | |
80 let errno = error.raw_os_error().expect("expected real OS error"); | |
81 self.outcome | |
82 .bad | |
83 .push((hg_path.to_owned().into(), BadMatch::OsError(errno))) | |
84 }) | |
85 } | |
86 | |
72 fn traverse_fs_directory_and_dirstate( | 87 fn traverse_fs_directory_and_dirstate( |
73 &mut self, | 88 &mut self, |
74 has_ignored_ancestor: bool, | 89 has_ignored_ancestor: bool, |
75 dirstate_nodes: &'tree mut ChildNodes, | 90 dirstate_nodes: &'tree mut ChildNodes, |
76 directory_hg_path: &HgPath, | 91 directory_hg_path: &'tree HgPath, |
77 fs_path: &Path, | 92 directory_fs_path: &Path, |
78 is_at_repo_root: bool, | 93 is_at_repo_root: bool, |
79 ) { | 94 ) { |
80 // TODO: handle I/O errors | 95 let mut fs_entries = if let Ok(entries) = self.read_dir( |
81 let mut fs_entries = | 96 directory_hg_path, |
82 DirEntry::read_dir(fs_path, is_at_repo_root).unwrap(); | 97 directory_fs_path, |
98 is_at_repo_root, | |
99 ) { | |
100 entries | |
101 } else { | |
102 return; | |
103 }; | |
83 | 104 |
84 // `merge_join_by` requires both its input iterators to be sorted: | 105 // `merge_join_by` requires both its input iterators to be sorted: |
85 | 106 |
86 // * `BTreeMap` iterates according to keys’ ordering by definition | 107 // * `BTreeMap` iterates according to keys’ ordering by definition |
87 | 108 |
293 // ignored | 314 // ignored |
294 self.options.list_unknown || self.options.list_ignored | 315 self.options.list_unknown || self.options.list_ignored |
295 }; | 316 }; |
296 if traverse_children { | 317 if traverse_children { |
297 let is_at_repo_root = false; | 318 let is_at_repo_root = false; |
298 // TODO: handle I/O errors | 319 if let Ok(children_fs_entries) = self.read_dir( |
299 let children_fs_entries = | 320 &hg_path, |
300 DirEntry::read_dir(&fs_entry.full_path, is_at_repo_root) | 321 &fs_entry.full_path, |
301 .unwrap(); | 322 is_at_repo_root, |
302 for child_fs_entry in children_fs_entries { | 323 ) { |
303 self.traverse_fs_only( | 324 for child_fs_entry in children_fs_entries { |
304 is_ignored, | 325 self.traverse_fs_only( |
305 &hg_path, | 326 is_ignored, |
306 &child_fs_entry, | 327 &hg_path, |
307 ) | 328 &child_fs_entry, |
329 ) | |
330 } | |
308 } | 331 } |
309 } | 332 } |
310 if self.options.collect_traversed_dirs { | 333 if self.options.collect_traversed_dirs { |
311 self.outcome.traversed.push(hg_path.into()) | 334 self.outcome.traversed.push(hg_path.into()) |
312 } | 335 } |