Patchwork D10549: dirstate-tree: Handle I/O errors in status

login
register
mail settings
Submitter phabricator
Date May 3, 2021, 10:28 a.m.
Message ID <differential-rev-PHID-DREV-crumtxhynej6n266wtr3-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48866/
State Superseded
Headers show

Comments

phabricator - May 3, 2021, 10:28 a.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Errors such as insufficient permissions when listing a directory are logged,
  and the algorithm continues without considering that directory.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D10549

AFFECTED FILES
  rust/hg-core/src/dirstate_tree/status.rs

CHANGE DETAILS




To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/rust/hg-core/src/dirstate_tree/status.rs b/rust/hg-core/src/dirstate_tree/status.rs
--- a/rust/hg-core/src/dirstate_tree/status.rs
+++ b/rust/hg-core/src/dirstate_tree/status.rs
@@ -6,6 +6,7 @@ 
 use crate::matchers::Matcher;
 use crate::utils::files::get_bytes_from_os_string;
 use crate::utils::hg_path::HgPath;
+use crate::BadMatch;
 use crate::DirstateStatus;
 use crate::EntryState;
 use crate::HgPathBuf;
@@ -69,17 +70,37 @@ 
 }
 
 impl<'tree, 'a> StatusCommon<'tree, 'a> {
+    fn read_dir(
+        &mut self,
+        hg_path: &HgPath,
+        fs_path: &Path,
+        is_at_repo_root: bool,
+    ) -> Result<Vec<DirEntry>, ()> {
+        DirEntry::read_dir(fs_path, is_at_repo_root).map_err(|error| {
+            let errno = error.raw_os_error().expect("expected real OS error");
+            self.outcome
+                .bad
+                .push((hg_path.to_owned().into(), BadMatch::OsError(errno)))
+        })
+    }
+
     fn traverse_fs_directory_and_dirstate(
         &mut self,
         has_ignored_ancestor: bool,
         dirstate_nodes: &'tree mut ChildNodes,
-        directory_hg_path: &HgPath,
-        fs_path: &Path,
+        directory_hg_path: &'tree HgPath,
+        directory_fs_path: &Path,
         is_at_repo_root: bool,
     ) {
-        // TODO: handle I/O errors
-        let mut fs_entries =
-            DirEntry::read_dir(fs_path, is_at_repo_root).unwrap();
+        let mut fs_entries = if let Ok(entries) = self.read_dir(
+            directory_hg_path,
+            directory_fs_path,
+            is_at_repo_root,
+        ) {
+            entries
+        } else {
+            return;
+        };
 
         // `sort_unstable_by_key` doesn’t allow keys borrowing from the value:
         // https://github.com/rust-lang/rust/issues/34162
@@ -278,16 +299,18 @@ 
             };
             if traverse_children {
                 let is_at_repo_root = false;
-                // TODO: handle I/O errors
-                let children_fs_entries =
-                    DirEntry::read_dir(&fs_entry.full_path, is_at_repo_root)
-                        .unwrap();
-                for child_fs_entry in children_fs_entries {
-                    self.traverse_fs_only(
-                        is_ignored,
-                        &hg_path,
-                        &child_fs_entry,
-                    )
+                if let Ok(children_fs_entries) = self.read_dir(
+                    &hg_path,
+                    &fs_entry.full_path,
+                    is_at_repo_root,
+                ) {
+                    for child_fs_entry in children_fs_entries {
+                        self.traverse_fs_only(
+                            is_ignored,
+                            &hg_path,
+                            &child_fs_entry,
+                        )
+                    }
                 }
             }
             if self.options.collect_traversed_dirs {