rust/hg-core/src/dirstate_tree/status.rs
changeset 48205 320de901896a
parent 48204 d2f760c2c91c
child 48230 15dedc0c5c35
equal deleted inserted replaced
48204:d2f760c2c91c 48205:320de901896a
     1 use crate::dirstate::entry::Timestamp;
     1 use crate::dirstate::entry::TruncatedTimestamp;
     2 use crate::dirstate::status::IgnoreFnType;
     2 use crate::dirstate::status::IgnoreFnType;
     3 use crate::dirstate_tree::dirstate_map::BorrowedPath;
     3 use crate::dirstate_tree::dirstate_map::BorrowedPath;
     4 use crate::dirstate_tree::dirstate_map::ChildNodesRef;
     4 use crate::dirstate_tree::dirstate_map::ChildNodesRef;
     5 use crate::dirstate_tree::dirstate_map::DirstateMap;
     5 use crate::dirstate_tree::dirstate_map::DirstateMap;
     6 use crate::dirstate_tree::dirstate_map::NodeData;
     6 use crate::dirstate_tree::dirstate_map::NodeData;
   124     dmap: &'tree DirstateMap<'on_disk>,
   124     dmap: &'tree DirstateMap<'on_disk>,
   125     options: StatusOptions,
   125     options: StatusOptions,
   126     matcher: &'a (dyn Matcher + Sync),
   126     matcher: &'a (dyn Matcher + Sync),
   127     ignore_fn: IgnoreFnType<'a>,
   127     ignore_fn: IgnoreFnType<'a>,
   128     outcome: Mutex<DirstateStatus<'on_disk>>,
   128     outcome: Mutex<DirstateStatus<'on_disk>>,
   129     new_cachable_directories: Mutex<Vec<(Cow<'on_disk, HgPath>, Timestamp)>>,
   129     new_cachable_directories:
       
   130         Mutex<Vec<(Cow<'on_disk, HgPath>, TruncatedTimestamp)>>,
   130     outated_cached_directories: Mutex<Vec<Cow<'on_disk, HgPath>>>,
   131     outated_cached_directories: Mutex<Vec<Cow<'on_disk, HgPath>>>,
   131 
   132 
   132     /// Whether ignore files like `.hgignore` have changed since the previous
   133     /// Whether ignore files like `.hgignore` have changed since the previous
   133     /// time a `status()` call wrote their hash to the dirstate. `None` means
   134     /// time a `status()` call wrote their hash to the dirstate. `None` means
   134     /// we don’t know as this run doesn’t list either ignored or uknown files
   135     /// we don’t know as this run doesn’t list either ignored or uknown files
   163     fn check_for_outdated_directory_cache(
   164     fn check_for_outdated_directory_cache(
   164         &self,
   165         &self,
   165         dirstate_node: &NodeRef<'tree, 'on_disk>,
   166         dirstate_node: &NodeRef<'tree, 'on_disk>,
   166     ) -> Result<(), DirstateV2ParseError> {
   167     ) -> Result<(), DirstateV2ParseError> {
   167         if self.ignore_patterns_have_changed == Some(true)
   168         if self.ignore_patterns_have_changed == Some(true)
   168             && dirstate_node.cached_directory_mtime().is_some()
   169             && dirstate_node.cached_directory_mtime()?.is_some()
   169         {
   170         {
   170             self.outated_cached_directories.lock().unwrap().push(
   171             self.outated_cached_directories.lock().unwrap().push(
   171                 dirstate_node
   172                 dirstate_node
   172                     .full_path_borrowed(self.dmap.on_disk)?
   173                     .full_path_borrowed(self.dmap.on_disk)?
   173                     .detach_from_tree(),
   174                     .detach_from_tree(),
   180     /// `symlink_metadata` for child nodes that exist in the dirstate and don’t
   181     /// `symlink_metadata` for child nodes that exist in the dirstate and don’t
   181     /// need to call `read_dir`.
   182     /// need to call `read_dir`.
   182     fn can_skip_fs_readdir(
   183     fn can_skip_fs_readdir(
   183         &self,
   184         &self,
   184         directory_metadata: Option<&std::fs::Metadata>,
   185         directory_metadata: Option<&std::fs::Metadata>,
   185         cached_directory_mtime: Option<Timestamp>,
   186         cached_directory_mtime: Option<TruncatedTimestamp>,
   186     ) -> bool {
   187     ) -> bool {
   187         if !self.options.list_unknown && !self.options.list_ignored {
   188         if !self.options.list_unknown && !self.options.list_ignored {
   188             // All states that we care about listing have corresponding
   189             // All states that we care about listing have corresponding
   189             // dirstate entries.
   190             // dirstate entries.
   190             // This happens for example with `hg status -mard`.
   191             // This happens for example with `hg status -mard`.
   197                 // The dirstate contains a cached mtime for this directory, set
   198                 // The dirstate contains a cached mtime for this directory, set
   198                 // by a previous run of the `status` algorithm which found this
   199                 // by a previous run of the `status` algorithm which found this
   199                 // directory eligible for `read_dir` caching.
   200                 // directory eligible for `read_dir` caching.
   200                 if let Some(meta) = directory_metadata {
   201                 if let Some(meta) = directory_metadata {
   201                     if let Ok(current_mtime) = meta.modified() {
   202                     if let Ok(current_mtime) = meta.modified() {
   202                         let current_mtime = Timestamp::from(current_mtime);
   203                         let truncated =
   203                         if current_mtime == cached_mtime {
   204                             TruncatedTimestamp::from(current_mtime);
       
   205                         if truncated.very_likely_equal(&cached_mtime) {
   204                             // The mtime of that directory has not changed
   206                             // The mtime of that directory has not changed
   205                             // since then, which means that the results of
   207                             // since then, which means that the results of
   206                             // `read_dir` should also be unchanged.
   208                             // `read_dir` should also be unchanged.
   207                             return true;
   209                             return true;
   208                         }
   210                         }
   220         has_ignored_ancestor: bool,
   222         has_ignored_ancestor: bool,
   221         dirstate_nodes: ChildNodesRef<'tree, 'on_disk>,
   223         dirstate_nodes: ChildNodesRef<'tree, 'on_disk>,
   222         directory_hg_path: &BorrowedPath<'tree, 'on_disk>,
   224         directory_hg_path: &BorrowedPath<'tree, 'on_disk>,
   223         directory_fs_path: &Path,
   225         directory_fs_path: &Path,
   224         directory_metadata: Option<&std::fs::Metadata>,
   226         directory_metadata: Option<&std::fs::Metadata>,
   225         cached_directory_mtime: Option<Timestamp>,
   227         cached_directory_mtime: Option<TruncatedTimestamp>,
   226         is_at_repo_root: bool,
   228         is_at_repo_root: bool,
   227     ) -> Result<bool, DirstateV2ParseError> {
   229     ) -> Result<bool, DirstateV2ParseError> {
   228         if self.can_skip_fs_readdir(directory_metadata, cached_directory_mtime)
   230         if self.can_skip_fs_readdir(directory_metadata, cached_directory_mtime)
   229         {
   231         {
   230             dirstate_nodes
   232             dirstate_nodes
   361                     is_ignored,
   363                     is_ignored,
   362                     dirstate_node.children(self.dmap.on_disk)?,
   364                     dirstate_node.children(self.dmap.on_disk)?,
   363                     hg_path,
   365                     hg_path,
   364                     fs_path,
   366                     fs_path,
   365                     Some(fs_metadata),
   367                     Some(fs_metadata),
   366                     dirstate_node.cached_directory_mtime(),
   368                     dirstate_node.cached_directory_mtime()?,
   367                     is_at_repo_root,
   369                     is_at_repo_root,
   368                 )?;
   370                 )?;
   369             self.maybe_save_directory_mtime(
   371             self.maybe_save_directory_mtime(
   370                 children_all_have_dirstate_node_or_are_ignored,
   372                 children_all_have_dirstate_node_or_are_ignored,
   371                 fs_metadata,
   373                 fs_metadata,
   464                     // directory change could potentially happen during exactly
   466                     // directory change could potentially happen during exactly
   465                     // the wrong tick.
   467                     // the wrong tick.
   466                     //
   468                     //
   467                     // We deem this scenario (unlike the previous one) to be
   469                     // We deem this scenario (unlike the previous one) to be
   468                     // unlikely enough in practice.
   470                     // unlikely enough in practice.
   469                     let timestamp = directory_mtime.into();
   471                     let truncated = TruncatedTimestamp::from(directory_mtime);
   470                     let cached = dirstate_node.cached_directory_mtime();
   472                     let is_up_to_date = if let Some(cached) =
   471                     if cached != Some(timestamp) {
   473                         dirstate_node.cached_directory_mtime()?
       
   474                     {
       
   475                         cached.very_likely_equal(&truncated)
       
   476                     } else {
       
   477                         false
       
   478                     };
       
   479                     if !is_up_to_date {
   472                         let hg_path = dirstate_node
   480                         let hg_path = dirstate_node
   473                             .full_path_borrowed(self.dmap.on_disk)?
   481                             .full_path_borrowed(self.dmap.on_disk)?
   474                             .detach_from_tree();
   482                             .detach_from_tree();
   475                         self.new_cachable_directories
   483                         self.new_cachable_directories
   476                             .lock()
   484                             .lock()
   477                             .unwrap()
   485                             .unwrap()
   478                             .push((hg_path, timestamp))
   486                             .push((hg_path, truncated))
   479                     }
   487                     }
   480                 }
   488                 }
   481             }
   489             }
   482         }
   490         }
   483         Ok(())
   491         Ok(())