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 @@ -433,16 +433,21 @@ impl<'a, 'tree, 'on_disk> StatusCommon<' return Ok(children_all_have_dirstate_node_or_are_ignored); } + let readdir_succeeded; let mut fs_entries = if let Ok(entries) = self.read_dir( directory_hg_path, &directory_entry.fs_path, is_at_repo_root, ) { + readdir_succeeded = true; entries } else { // Treat an unreadable directory (typically because of insufficient // permissions) like an empty directory. `self.read_dir` has // already called `self.io_error` so a warning will be emitted. + // We still need to remember that there was an error so that we + // know not to cache this result. + readdir_succeeded = false; Vec::new() }; @@ -495,6 +500,7 @@ impl<'a, 'tree, 'on_disk> StatusCommon<' Ok(has_dirstate_node_or_is_ignored) }) .try_reduce(|| true, |a, b| Ok(a && b)) + .map(|res| res && readdir_succeeded) } fn traverse_fs_and_dirstate<'ancestor>( diff --git a/tests/test-status-eacces.t b/tests/test-status-eacces.t --- a/tests/test-status-eacces.t +++ b/tests/test-status-eacces.t @@ -9,6 +9,7 @@ > EOF #endif + The proliferation of status implementations can be confusing: - The pure python implementation: (no-rhg pure !) @@ -31,20 +32,17 @@ The proliferation of status implementati ! d1/x (rhg !) ! d1/x (no-rhg rust !) $ hg status - d1: $EACCES$ (rhg dirstate-v1 !) - d1: $EACCES$ (no-rhg rust dirstate-v1 !) + d1: $EACCES$ (rhg !) + d1: $EACCES$ (no-rhg rust !) d1: $EACCES$ (no-rust no-rhg !) - ! d1/x (rust dirstate-v1 !) - ! d1/x (no-rust rhg dirstate-v1 !) + ! d1/x (rust !) + ! d1/x (no-rust rhg !) $ chmod +r d1 $ hg status - ? d1/y (rhg dirstate-v1 !) - ? d1/y (no-rhg rust dirstate-v1 !) + ? d1/y (rhg !) + ? d1/y (no-rhg rust !) ? d1/y (no-rhg no-rust !) -TODO: make the tests marked with (dirstate-v1) above work the same way -with dirstate-v2 as well. - $ touch d1/z $ hg status ? d1/y