Patchwork D10919: rust: Document the DirstateMapMethods trait

login
register
mail settings
Submitter phabricator
Date July 1, 2021, 4:51 p.m.
Message ID <differential-rev-PHID-DREV-nxsde5rts5hurtqwe4jh-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/49233/
State Superseded
Headers show

Comments

phabricator - July 1, 2021, 4:51 p.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D10919

AFFECTED FILES
  rust/hg-core/src/dirstate_tree/dispatch.rs
  rust/hg-core/src/dirstate_tree/on_disk.rs

CHANGE DETAILS




To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs b/rust/hg-core/src/dirstate_tree/on_disk.rs
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs
@@ -78,7 +78,7 @@ 
     children: ChildNodes,
     pub(super) tracked_descendants_count: Size,
 
-    /// Dependending on the value of `state`:
+    /// Depending on the value of `state`:
     ///
     /// * A null byte: `data` is not used.
     ///
diff --git a/rust/hg-core/src/dirstate_tree/dispatch.rs b/rust/hg-core/src/dirstate_tree/dispatch.rs
--- a/rust/hg-core/src/dirstate_tree/dispatch.rs
+++ b/rust/hg-core/src/dirstate_tree/dispatch.rs
@@ -16,9 +16,34 @@ 
 use crate::StatusError;
 use crate::StatusOptions;
 
+/// `rust/hg-cpython/src/dirstate/dirstate_map.rs` implements in Rust a
+/// `DirstateMap` Python class that wraps `Box<dyn DirstateMapMethods + Send>`,
+/// a trait object of this trait. Except for constructors, this trait defines
+/// all APIs that the class needs to interact with its inner dirstate map.
+///
+/// A trait object is used to support two different concrete types:
+///
+/// * `rust/hg-core/src/dirstate/dirstate_map.rs` defines the "flat dirstate
+///   map" which is based on a few large `HgPath`-keyed `HashMap` and `HashSet`
+///   fields.
+/// * `rust/hg-core/src/dirstate_tree/dirstate_map.rs` defines the "tree
+///   dirstate map" based on a tree data struture with nodes for directories
+///   containing child nodes for their files and sub-directories. This tree
+///   enables a more efficient algorithm for `hg status`, but its details are
+///   abstracted in this trait.
+///
+/// The dirstate map associates paths of files in the working directory to
+/// various information about the state of those files.
 pub trait DirstateMapMethods {
+    /// Remove information about all files in this map
     fn clear(&mut self);
 
+    /// Add or change the information associated to a given file.
+    ///
+    /// `old_state` is the state in the entry that `get` would have returned
+    /// before this call, or `EntryState::Unknown` if there was no such entry.
+    ///
+    /// `entry.state` should never be `EntryState::Unknown`.
     fn add_file(
         &mut self,
         filename: &HgPath,
@@ -26,6 +51,13 @@ 
         entry: DirstateEntry,
     ) -> Result<(), DirstateError>;
 
+    /// Mark a file as "removed" (as in `hg rm`).
+    ///
+    /// `old_state` is the state in the entry that `get` would have returned
+    /// before this call, or `EntryState::Unknown` if there was no such entry.
+    ///
+    /// `size` is not actually a size but the 0 or -1 or -2 value that would be
+    /// put in the size field in the dirstate-v1 format.
     fn remove_file(
         &mut self,
         filename: &HgPath,
@@ -33,62 +65,127 @@ 
         size: i32,
     ) -> Result<(), DirstateError>;
 
+    /// Drop information about this file from the map if any, and return
+    /// whether there was any.
+    ///
+    /// `get` will now return `None` for this filename.
+    ///
+    /// `old_state` is the state in the entry that `get` would have returned
+    /// before this call, or `EntryState::Unknown` if there was no such entry.
     fn drop_file(
         &mut self,
         filename: &HgPath,
         old_state: EntryState,
     ) -> Result<bool, DirstateError>;
 
+    /// Among given files, mark the stored `mtime` as ambiguous if there is one
+    /// (if `state == EntryState::Normal`) equal to the given current Unix
+    /// timestamp.
     fn clear_ambiguous_times(
         &mut self,
         filenames: Vec<HgPathBuf>,
         now: i32,
     ) -> Result<(), DirstateV2ParseError>;
 
+    /// Return whether the map has an "non-normal" entry for the given
+    /// filename. That is, any entry with a `state` other than
+    /// `EntryState::Normal` or with an ambiguous `mtime`.
     fn non_normal_entries_contains(
         &mut self,
         key: &HgPath,
     ) -> Result<bool, DirstateV2ParseError>;
 
+    /// Mark the given path as "normal" file. This is only relevant in the flat
+    /// dirstate map where there is a separate `HashSet` that needs to be kept
+    /// up to date.
     fn non_normal_entries_remove(&mut self, key: &HgPath);
 
+    /// Return an iterator of paths whose respective entry are either
+    /// "non-normal" (see `non_normal_entries_contains`) or "from other
+    /// parent".
+    ///
+    /// If that information is cached, create the cache as needed.
+    ///
+    /// "From other parent" is defined as `state == Normal && size == -2`.
+    ///
+    /// Because parse errors can happen during iteration, the iterated items
+    /// are `Result`s.
     fn non_normal_or_other_parent_paths(
         &mut self,
     ) -> Box<dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + '_>;
 
+    /// Create the cache for `non_normal_or_other_parent_paths` if needed.
+    ///
+    /// If `force` is true, the cache is re-created even if it already exists.
     fn set_non_normal_other_parent_entries(&mut self, force: bool);
 
+    /// Return an iterator of paths whose respective entry are "non-normal"
+    /// (see `non_normal_entries_contains`).
+    ///
+    /// If that information is cached, create the cache as needed.
+    ///
+    /// Because parse errors can happen during iteration, the iterated items
+    /// are `Result`s.
     fn iter_non_normal_paths(
         &mut self,
     ) -> Box<
         dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
     >;
 
+    /// Same as `iter_non_normal_paths`, but takes `&self` instead of `&mut
+    /// self`.
+    ///
+    /// Panics if a cache is necessary but does not exist yet.
     fn iter_non_normal_paths_panic(
         &self,
     ) -> Box<
         dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
     >;
 
+    /// Return an iterator of paths whose respective entry are "from other
+    /// parent".
+    ///
+    /// If that information is cached, create the cache as needed.
+    ///
+    /// "From other parent" is defined as `state == Normal && size == -2`.
+    ///
+    /// Because parse errors can happen during iteration, the iterated items
+    /// are `Result`s.
     fn iter_other_parent_paths(
         &mut self,
     ) -> Box<
         dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
     >;
 
+    /// Returns whether the sub-tree rooted at the given directory contains any
+    /// tracked file.
+    ///
+    /// A file is tracked if it has a `state` other than `EntryState::Removed`.
     fn has_tracked_dir(
         &mut self,
         directory: &HgPath,
     ) -> Result<bool, DirstateError>;
 
+    /// Returns whether the sub-tree rooted at the given directory contains any
+    /// file with a dirstate entry.
     fn has_dir(&mut self, directory: &HgPath) -> Result<bool, DirstateError>;
 
+    /// Clear mtimes that are ambigous with `now` (similar to
+    /// `clear_ambiguous_times` but for all files in the dirstate map), and
+    /// serialize bytes to write the `.hg/dirstate` file to disk in dirstate-v1
+    /// format.
     fn pack_v1(
         &mut self,
         parents: DirstateParents,
         now: Timestamp,
     ) -> Result<Vec<u8>, DirstateError>;
 
+    /// Clear mtimes that are ambigous with `now` (similar to
+    /// `clear_ambiguous_times` but for all files in the dirstate map), and
+    /// serialize bytes to write the `.hg/dirstate` file to disk in dirstate-v2
+    /// format.
+    ///
+    /// Note: this is only supported by the tree dirstate map.
     fn pack_v2(
         &mut self,
         parents: DirstateParents,
@@ -99,6 +196,11 @@ 
 
     fn set_dirs(&mut self) -> Result<(), DirstateError>;
 
+    /// Run the status algorithm.
+    ///
+    /// This is not sematically a method of the dirstate map, but a different
+    /// algorithm is used for the flat v.s. tree dirstate map so having it in
+    /// this trait enables the same dynamic dispatch as with other methods.
     fn status<'a>(
         &'a mut self,
         matcher: &'a (dyn Matcher + Sync),
@@ -107,43 +209,66 @@ 
         options: StatusOptions,
     ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>;
 
+    /// Returns how many files in the dirstate map have a recorded copy source.
     fn copy_map_len(&self) -> usize;
 
+    /// Returns an iterator of `(path, copy_source)` for all files that have a
+    /// copy source.
     fn copy_map_iter(&self) -> CopyMapIter<'_>;
 
+    /// Returns whether the givef file has a copy source.
     fn copy_map_contains_key(
         &self,
         key: &HgPath,
     ) -> Result<bool, DirstateV2ParseError>;
 
+    /// Returns the copy source for the given file.
     fn copy_map_get(
         &self,
         key: &HgPath,
     ) -> Result<Option<&HgPath>, DirstateV2ParseError>;
 
+    /// Removes the recorded copy source if any for the given file, and returns
+    /// it.
     fn copy_map_remove(
         &mut self,
         key: &HgPath,
     ) -> Result<Option<HgPathBuf>, DirstateV2ParseError>;
 
+    /// Set the given `value` copy source for the given `key` file.
     fn copy_map_insert(
         &mut self,
         key: HgPathBuf,
         value: HgPathBuf,
     ) -> Result<Option<HgPathBuf>, DirstateV2ParseError>;
 
+    /// Returns the number of files that have an entry.
     fn len(&self) -> usize;
 
+    /// Returns whether the given file has an entry.
     fn contains_key(&self, key: &HgPath)
         -> Result<bool, DirstateV2ParseError>;
 
+    /// Returns the entry, if any, for the given file.
     fn get(
         &self,
         key: &HgPath,
     ) -> Result<Option<DirstateEntry>, DirstateV2ParseError>;
 
+    /// Returns a `(path, entry)` iterator of files that have an entry.
+    ///
+    /// Because parse errors can happen during iteration, the iterated items
+    /// are `Result`s.
     fn iter(&self) -> StateMapIter<'_>;
 
+    /// In the tree dirstate, return an iterator of "directory" (entry-less)
+    /// nodes with the data stored for them. This is for `hg debugdirstate
+    /// --dirs`.
+    ///
+    /// In the flat dirstate, returns an empty iterator.
+    ///
+    /// Because parse errors can happen during iteration, the iterated items
+    /// are `Result`s.
     fn iter_directories(
         &self,
     ) -> Box<