changeset 50294:bae51b50a5cf stable

dirstate-v2: fix an incorrect handling of readdir errors Make sure not to cache the results of a failed readdir call.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Mon, 13 Mar 2023 14:15:34 +0000
parents f1f3a8eb93a1
children 86d2a28c018e
files rust/hg-core/src/dirstate_tree/status.rs tests/test-status-eacces.t
diffstat 2 files changed, 13 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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>(
--- 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