dirstate-v2: fix an incorrect handling of readdir errors
Make sure not to cache the results of a failed readdir call.
--- 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