##// END OF EJS Templates
dirstate-v2: skip evaluation of hgignore regex on cached directories...
Arseniy Alekseyev -
r50415:eb02decd default
parent child Browse files
Show More
@@ -468,6 +468,7 b' dependencies = ['
468 468 "log",
469 469 "memmap2",
470 470 "micro-timer",
471 "once_cell",
471 472 "ouroboros",
472 473 "pretty_assertions",
473 474 "rand 0.8.5",
@@ -687,6 +688,12 b' dependencies = ['
687 688 ]
688 689
689 690 [[package]]
691 name = "once_cell"
692 version = "1.14.0"
693 source = "registry+https://github.com/rust-lang/crates.io-index"
694 checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
695
696 [[package]]
690 697 name = "opaque-debug"
691 698 version = "0.3.0"
692 699 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -35,6 +35,9 b' log = "0.4.8"'
35 35 memmap2 = { version = "0.5.3", features = ["stable_deref_trait"] }
36 36 zstd = "0.5.3"
37 37 format-bytes = "0.3.0"
38 # once_cell 1.15 uses edition 2021, while the heptapod CI
39 # uses an old version of Cargo that doesn't support it.
40 once_cell = "=1.14.0"
38 41
39 42 # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until
40 43 # we have a clearer view of which backend is the fastest.
@@ -20,6 +20,7 b' use crate::PatternFileWarning;'
20 20 use crate::StatusError;
21 21 use crate::StatusOptions;
22 22 use micro_timer::timed;
23 use once_cell::sync::OnceCell;
23 24 use rayon::prelude::*;
24 25 use sha1::{Digest, Sha1};
25 26 use std::borrow::Cow;
@@ -126,14 +127,14 b" pub fn status<'dirstate>("
126 127 };
127 128 let is_at_repo_root = true;
128 129 let hg_path = &BorrowedPath::OnDisk(HgPath::new(""));
129 let has_ignored_ancestor = false;
130 let has_ignored_ancestor = HasIgnoredAncestor::create(None, hg_path);
130 131 let root_cached_mtime = None;
131 132 let root_dir_metadata = None;
132 133 // If the path we have for the repository root is a symlink, do follow it.
133 134 // (As opposed to symlinks within the working directory which are not
134 135 // followed, using `std::fs::symlink_metadata`.)
135 136 common.traverse_fs_directory_and_dirstate(
136 has_ignored_ancestor,
137 &has_ignored_ancestor,
137 138 dmap.root.as_ref(),
138 139 hg_path,
139 140 &root_dir,
@@ -196,6 +197,40 b' enum Outcome {'
196 197 Unsure,
197 198 }
198 199
200 /// Lazy computation of whether a given path has a hgignored
201 /// ancestor.
202 struct HasIgnoredAncestor<'a> {
203 /// `path` and `parent` constitute the inputs to the computation,
204 /// `cache` stores the outcome.
205 path: &'a HgPath,
206 parent: Option<&'a HasIgnoredAncestor<'a>>,
207 cache: OnceCell<bool>,
208 }
209
210 impl<'a> HasIgnoredAncestor<'a> {
211 fn create(
212 parent: Option<&'a HasIgnoredAncestor<'a>>,
213 path: &'a HgPath,
214 ) -> HasIgnoredAncestor<'a> {
215 Self {
216 path,
217 parent,
218 cache: OnceCell::new(),
219 }
220 }
221
222 fn force<'b>(&self, ignore_fn: &IgnoreFnType<'b>) -> bool {
223 match self.parent {
224 None => false,
225 Some(parent) => {
226 *(parent.cache.get_or_init(|| {
227 parent.force(ignore_fn) || ignore_fn(&self.path)
228 }))
229 }
230 }
231 }
232 }
233
199 234 impl<'a, 'tree, 'on_disk> StatusCommon<'a, 'tree, 'on_disk> {
200 235 fn push_outcome(
201 236 &self,
@@ -318,9 +353,9 b" impl<'a, 'tree, 'on_disk> StatusCommon<'"
318 353
319 354 /// Returns whether all child entries of the filesystem directory have a
320 355 /// corresponding dirstate node or are ignored.
321 fn traverse_fs_directory_and_dirstate(
356 fn traverse_fs_directory_and_dirstate<'ancestor>(
322 357 &self,
323 has_ignored_ancestor: bool,
358 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>,
324 359 dirstate_nodes: ChildNodesRef<'tree, 'on_disk>,
325 360 directory_hg_path: &BorrowedPath<'tree, 'on_disk>,
326 361 directory_fs_path: &Path,
@@ -418,7 +453,7 b" impl<'a, 'tree, 'on_disk> StatusCommon<'"
418 453 }
419 454 Right(fs_entry) => {
420 455 has_dirstate_node_or_is_ignored = self.traverse_fs_only(
421 has_ignored_ancestor,
456 has_ignored_ancestor.force(&self.ignore_fn),
422 457 directory_hg_path,
423 458 fs_entry,
424 459 )
@@ -429,12 +464,12 b" impl<'a, 'tree, 'on_disk> StatusCommon<'"
429 464 .try_reduce(|| true, |a, b| Ok(a && b))
430 465 }
431 466
432 fn traverse_fs_and_dirstate(
467 fn traverse_fs_and_dirstate<'ancestor>(
433 468 &self,
434 469 fs_path: &Path,
435 470 fs_metadata: &std::fs::Metadata,
436 471 dirstate_node: NodeRef<'tree, 'on_disk>,
437 has_ignored_ancestor: bool,
472 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>,
438 473 ) -> Result<(), DirstateV2ParseError> {
439 474 self.check_for_outdated_directory_cache(&dirstate_node)?;
440 475 let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?;
@@ -454,11 +489,14 b" impl<'a, 'tree, 'on_disk> StatusCommon<'"
454 489 .traversed
455 490 .push(hg_path.detach_from_tree())
456 491 }
457 let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path);
492 let is_ignored = HasIgnoredAncestor::create(
493 Some(&has_ignored_ancestor),
494 hg_path,
495 );
458 496 let is_at_repo_root = false;
459 497 let children_all_have_dirstate_node_or_are_ignored = self
460 498 .traverse_fs_directory_and_dirstate(
461 is_ignored,
499 &is_ignored,
462 500 dirstate_node.children(self.dmap.on_disk)?,
463 501 hg_path,
464 502 fs_path,
@@ -472,14 +510,14 b" impl<'a, 'tree, 'on_disk> StatusCommon<'"
472 510 dirstate_node,
473 511 )?
474 512 } else {
475 if file_or_symlink && self.matcher.matches(hg_path) {
513 if file_or_symlink && self.matcher.matches(&hg_path) {
476 514 if let Some(entry) = dirstate_node.entry()? {
477 515 if !entry.any_tracked() {
478 516 // Forward-compat if we start tracking unknown/ignored
479 517 // files for caching reasons
480 518 self.mark_unknown_or_ignored(
481 has_ignored_ancestor,
482 hg_path,
519 has_ignored_ancestor.force(&self.ignore_fn),
520 &hg_path,
483 521 );
484 522 }
485 523 if entry.added() {
@@ -495,7 +533,7 b" impl<'a, 'tree, 'on_disk> StatusCommon<'"
495 533 // `node.entry.is_none()` indicates a "directory"
496 534 // node, but the filesystem has a file
497 535 self.mark_unknown_or_ignored(
498 has_ignored_ancestor,
536 has_ignored_ancestor.force(&self.ignore_fn),
499 537 hg_path,
500 538 );
501 539 }
General Comments 0
You need to be logged in to leave comments. Login now