comparison rust/hg-core/src/dirstate_tree/status.rs @ 49555:8ee3889bab92 stable

rust-status: save new dircache even if just invalidated There was a functional race between invalidating the cache (not acted upon until the end of the status algorithm) and populating the new cache (which relies upon an up-to-date version of the cache). We simply inform the cache populating function that we've just invalidated the cache for this particular directory since the information is present in the same scope.
author Raphaël Gomès <rgomes@octobus.net>
date Wed, 19 Oct 2022 16:28:41 +0200
parents ecf9788cd9c4
children 363923bd51cd
comparison
equal deleted inserted replaced
49554:ecf9788cd9c4 49555:8ee3889bab92
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