# HG changeset patch # User Arseniy Alekseyev # Date 1678716934 0 # Node ID bae51b50a5cf9f3613b34c4c1db9b47b14301834 # Parent f1f3a8eb93a1521ece5712fe9d2ad30d2c671a6d dirstate-v2: fix an incorrect handling of readdir errors Make sure not to cache the results of a failed readdir call. diff -r f1f3a8eb93a1 -r bae51b50a5cf rust/hg-core/src/dirstate_tree/status.rs --- a/rust/hg-core/src/dirstate_tree/status.rs Fri Mar 10 18:20:50 2023 +0000 +++ b/rust/hg-core/src/dirstate_tree/status.rs Mon Mar 13 14:15:34 2023 +0000 @@ -433,16 +433,21 @@ 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 @@ 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 -r f1f3a8eb93a1 -r bae51b50a5cf tests/test-status-eacces.t --- a/tests/test-status-eacces.t Fri Mar 10 18:20:50 2023 +0000 +++ b/tests/test-status-eacces.t Mon Mar 13 14:15:34 2023 +0000 @@ -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 @@ ! 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