301 } |
301 } |
302 |
302 |
303 fn check_for_outdated_directory_cache( |
303 fn check_for_outdated_directory_cache( |
304 &self, |
304 &self, |
305 dirstate_node: &NodeRef<'tree, 'on_disk>, |
305 dirstate_node: &NodeRef<'tree, 'on_disk>, |
306 ) -> Result<(), DirstateV2ParseError> { |
306 ) -> Result<bool, DirstateV2ParseError> { |
307 if self.ignore_patterns_have_changed == Some(true) |
307 if self.ignore_patterns_have_changed == Some(true) |
308 && dirstate_node.cached_directory_mtime()?.is_some() |
308 && dirstate_node.cached_directory_mtime()?.is_some() |
309 { |
309 { |
310 self.outdated_cached_directories.lock().unwrap().push( |
310 self.outdated_cached_directories.lock().unwrap().push( |
311 dirstate_node |
311 dirstate_node |
312 .full_path_borrowed(self.dmap.on_disk)? |
312 .full_path_borrowed(self.dmap.on_disk)? |
313 .detach_from_tree(), |
313 .detach_from_tree(), |
314 ) |
314 ); |
315 } |
315 return Ok(true); |
316 Ok(()) |
316 } |
|
317 Ok(false) |
317 } |
318 } |
318 |
319 |
319 /// If this returns true, we can get accurate results by only using |
320 /// If this returns true, we can get accurate results by only using |
320 /// `symlink_metadata` for child nodes that exist in the dirstate and don’t |
321 /// `symlink_metadata` for child nodes that exist in the dirstate and don’t |
321 /// need to call `read_dir`. |
322 /// need to call `read_dir`. |
471 fs_path: &Path, |
472 fs_path: &Path, |
472 fs_metadata: &std::fs::Metadata, |
473 fs_metadata: &std::fs::Metadata, |
473 dirstate_node: NodeRef<'tree, 'on_disk>, |
474 dirstate_node: NodeRef<'tree, 'on_disk>, |
474 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>, |
475 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>, |
475 ) -> Result<(), DirstateV2ParseError> { |
476 ) -> Result<(), DirstateV2ParseError> { |
476 self.check_for_outdated_directory_cache(&dirstate_node)?; |
477 let outdated_dircache = |
|
478 self.check_for_outdated_directory_cache(&dirstate_node)?; |
477 let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?; |
479 let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?; |
478 let file_type = fs_metadata.file_type(); |
480 let file_type = fs_metadata.file_type(); |
479 let file_or_symlink = file_type.is_file() || file_type.is_symlink(); |
481 let file_or_symlink = file_type.is_file() || file_type.is_symlink(); |
480 if !file_or_symlink { |
482 if !file_or_symlink { |
481 // If we previously had a file here, it was removed (with |
483 // If we previously had a file here, it was removed (with |
508 )?; |
510 )?; |
509 self.maybe_save_directory_mtime( |
511 self.maybe_save_directory_mtime( |
510 children_all_have_dirstate_node_or_are_ignored, |
512 children_all_have_dirstate_node_or_are_ignored, |
511 fs_metadata, |
513 fs_metadata, |
512 dirstate_node, |
514 dirstate_node, |
|
515 outdated_dircache, |
513 )? |
516 )? |
514 } else { |
517 } else { |
515 if file_or_symlink && self.matcher.matches(&hg_path) { |
518 if file_or_symlink && self.matcher.matches(&hg_path) { |
516 if let Some(entry) = dirstate_node.entry()? { |
519 if let Some(entry) = dirstate_node.entry()? { |
517 if !entry.any_tracked() { |
520 if !entry.any_tracked() { |
547 } |
550 } |
548 } |
551 } |
549 Ok(()) |
552 Ok(()) |
550 } |
553 } |
551 |
554 |
|
555 /// Save directory mtime if applicable. |
|
556 /// |
|
557 /// `outdated_directory_cache` is `true` if we've just invalidated the |
|
558 /// cache for this directory in `check_for_outdated_directory_cache`, |
|
559 /// which forces the update. |
552 fn maybe_save_directory_mtime( |
560 fn maybe_save_directory_mtime( |
553 &self, |
561 &self, |
554 children_all_have_dirstate_node_or_are_ignored: bool, |
562 children_all_have_dirstate_node_or_are_ignored: bool, |
555 directory_metadata: &std::fs::Metadata, |
563 directory_metadata: &std::fs::Metadata, |
556 dirstate_node: NodeRef<'tree, 'on_disk>, |
564 dirstate_node: NodeRef<'tree, 'on_disk>, |
|
565 outdated_directory_cache: bool, |
557 ) -> Result<(), DirstateV2ParseError> { |
566 ) -> Result<(), DirstateV2ParseError> { |
558 if !children_all_have_dirstate_node_or_are_ignored { |
567 if !children_all_have_dirstate_node_or_are_ignored { |
559 return Ok(()); |
568 return Ok(()); |
560 } |
569 } |
561 // All filesystem directory entries from `read_dir` have a |
570 // All filesystem directory entries from `read_dir` have a |
619 // the wrong tick. |
628 // the wrong tick. |
620 // |
629 // |
621 // We deem this scenario (unlike the previous one) to be |
630 // We deem this scenario (unlike the previous one) to be |
622 // unlikely enough in practice. |
631 // unlikely enough in practice. |
623 |
632 |
624 let is_up_to_date = |
633 let is_up_to_date = if let Some(cached) = |
625 if let Some(cached) = dirstate_node.cached_directory_mtime()? { |
634 dirstate_node.cached_directory_mtime()? |
626 cached.likely_equal(directory_mtime) |
635 { |
627 } else { |
636 !outdated_directory_cache && cached.likely_equal(directory_mtime) |
628 false |
637 } else { |
629 }; |
638 false |
|
639 }; |
630 if !is_up_to_date { |
640 if !is_up_to_date { |
631 let hg_path = dirstate_node |
641 let hg_path = dirstate_node |
632 .full_path_borrowed(self.dmap.on_disk)? |
642 .full_path_borrowed(self.dmap.on_disk)? |
633 .detach_from_tree(); |
643 .detach_from_tree(); |
634 self.new_cacheable_directories |
644 self.new_cacheable_directories |