[Updated] D12175: status: prefer relative paths in Rust code
SimonSapin
phabricator at mercurial-scm.org
Tue Feb 15 09:44:02 UTC 2022
Closed by commit rHG94e36b230990: status: prefer relative paths in Rust code (authored by SimonSapin).
This revision was automatically updated to reflect the committed changes.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D12175?vs=32174&id=32184
CHANGES SINCE LAST ACTION
https://phab.mercurial-scm.org/D12175/new/
REVISION DETAIL
https://phab.mercurial-scm.org/D12175
AFFECTED FILES
rust/hg-core/src/dirstate_tree/status.rs
CHANGE DETAILS
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
@@ -65,6 +65,26 @@
let filesystem_time_at_status_start =
filesystem_now(&root_dir).ok().map(TruncatedTimestamp::from);
+
+ // If the repository is under the current directory, prefer using a
+ // relative path, so the kernel needs to traverse fewer directory in every
+ // call to `read_dir` or `symlink_metadata`.
+ // This is effective in the common case where the current directory is the
+ // repository root.
+
+ // TODO: Better yet would be to use libc functions like `openat` and
+ // `fstatat` to remove such repeated traversals entirely, but the standard
+ // library does not provide APIs based on those.
+ // Maybe with a crate like https://crates.io/crates/openat instead?
+ let root_dir = if let Some(relative) = std::env::current_dir()
+ .ok()
+ .and_then(|cwd| root_dir.strip_prefix(cwd).ok())
+ {
+ relative
+ } else {
+ &root_dir
+ };
+
let outcome = DirstateStatus {
filesystem_time_at_status_start,
..Default::default()
@@ -752,13 +772,16 @@
/// * Elsewhere, we’re listing the content of a sub-repo. Return an empty
/// list instead.
fn read_dir(path: &Path, is_at_repo_root: bool) -> io::Result<Vec<Self>> {
+ // `read_dir` returns a "not found" error for the empty path
+ let at_cwd = path == Path::new("");
+ let read_dir_path = if at_cwd { Path::new(".") } else { path };
let mut results = Vec::new();
- for entry in path.read_dir()? {
+ for entry in read_dir_path.read_dir()? {
let entry = entry?;
let metadata = entry.metadata()?;
- let name = get_bytes_from_os_string(entry.file_name());
+ let file_name = entry.file_name();
// FIXME don't do this when cached
- if name == b".hg" {
+ if file_name == ".hg" {
if is_at_repo_root {
// Skip the repo’s own .hg (might be a symlink)
continue;
@@ -768,9 +791,15 @@
return Ok(Vec::new());
}
}
+ let full_path = if at_cwd {
+ file_name.clone().into()
+ } else {
+ entry.path()
+ };
+ let base_name = get_bytes_from_os_string(file_name).into();
results.push(DirEntry {
- base_name: name.into(),
- full_path: entry.path(),
+ base_name,
+ full_path,
metadata,
})
}
To: SimonSapin, #hg-reviewers, Alphare
Cc: mercurial-patches
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-patches/attachments/20220215/7e82dbca/attachment-0002.html>
More information about the Mercurial-patches
mailing list