Show More
@@ -65,6 +65,26 b" pub fn status<'tree, 'on_disk: 'tree>(" | |||||
65 |
|
65 | |||
66 | let filesystem_time_at_status_start = |
|
66 | let filesystem_time_at_status_start = | |
67 | filesystem_now(&root_dir).ok().map(TruncatedTimestamp::from); |
|
67 | filesystem_now(&root_dir).ok().map(TruncatedTimestamp::from); | |
|
68 | ||||
|
69 | // If the repository is under the current directory, prefer using a | |||
|
70 | // relative path, so the kernel needs to traverse fewer directory in every | |||
|
71 | // call to `read_dir` or `symlink_metadata`. | |||
|
72 | // This is effective in the common case where the current directory is the | |||
|
73 | // repository root. | |||
|
74 | ||||
|
75 | // TODO: Better yet would be to use libc functions like `openat` and | |||
|
76 | // `fstatat` to remove such repeated traversals entirely, but the standard | |||
|
77 | // library does not provide APIs based on those. | |||
|
78 | // Maybe with a crate like https://crates.io/crates/openat instead? | |||
|
79 | let root_dir = if let Some(relative) = std::env::current_dir() | |||
|
80 | .ok() | |||
|
81 | .and_then(|cwd| root_dir.strip_prefix(cwd).ok()) | |||
|
82 | { | |||
|
83 | relative | |||
|
84 | } else { | |||
|
85 | &root_dir | |||
|
86 | }; | |||
|
87 | ||||
68 | let outcome = DirstateStatus { |
|
88 | let outcome = DirstateStatus { | |
69 | filesystem_time_at_status_start, |
|
89 | filesystem_time_at_status_start, | |
70 | ..Default::default() |
|
90 | ..Default::default() | |
@@ -752,13 +772,16 b' impl DirEntry {' | |||||
752 | /// * Elsewhere, we’re listing the content of a sub-repo. Return an empty |
|
772 | /// * Elsewhere, we’re listing the content of a sub-repo. Return an empty | |
753 | /// list instead. |
|
773 | /// list instead. | |
754 | fn read_dir(path: &Path, is_at_repo_root: bool) -> io::Result<Vec<Self>> { |
|
774 | fn read_dir(path: &Path, is_at_repo_root: bool) -> io::Result<Vec<Self>> { | |
|
775 | // `read_dir` returns a "not found" error for the empty path | |||
|
776 | let at_cwd = path == Path::new(""); | |||
|
777 | let read_dir_path = if at_cwd { Path::new(".") } else { path }; | |||
755 | let mut results = Vec::new(); |
|
778 | let mut results = Vec::new(); | |
756 | for entry in path.read_dir()? { |
|
779 | for entry in read_dir_path.read_dir()? { | |
757 | let entry = entry?; |
|
780 | let entry = entry?; | |
758 | let metadata = entry.metadata()?; |
|
781 | let metadata = entry.metadata()?; | |
759 |
let name = |
|
782 | let file_name = entry.file_name(); | |
760 | // FIXME don't do this when cached |
|
783 | // FIXME don't do this when cached | |
761 |
if name == |
|
784 | if file_name == ".hg" { | |
762 | if is_at_repo_root { |
|
785 | if is_at_repo_root { | |
763 | // Skip the repo’s own .hg (might be a symlink) |
|
786 | // Skip the repo’s own .hg (might be a symlink) | |
764 | continue; |
|
787 | continue; | |
@@ -768,9 +791,15 b' impl DirEntry {' | |||||
768 | return Ok(Vec::new()); |
|
791 | return Ok(Vec::new()); | |
769 | } |
|
792 | } | |
770 | } |
|
793 | } | |
|
794 | let full_path = if at_cwd { | |||
|
795 | file_name.clone().into() | |||
|
796 | } else { | |||
|
797 | entry.path() | |||
|
798 | }; | |||
|
799 | let base_name = get_bytes_from_os_string(file_name).into(); | |||
771 | results.push(DirEntry { |
|
800 | results.push(DirEntry { | |
772 |
base_name |
|
801 | base_name, | |
773 |
full_path |
|
802 | full_path, | |
774 | metadata, |
|
803 | metadata, | |
775 | }) |
|
804 | }) | |
776 | } |
|
805 | } |
General Comments 0
You need to be logged in to leave comments.
Login now