Details
Details
- Reviewers
pulkit - Group Reviewers
hg-reviewers - Commits
- rHG8851acad5906: rust: Document the DirstateMapMethods trait
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Branch
- default
- Lint
No Linters Available - Unit
No Unit Test Coverage
( )
pulkit |
hg-reviewers |
No Linters Available |
No Unit Test Coverage |
Path | Packages | |||
---|---|---|---|---|
M | rust/hg-core/src/dirstate_tree/dispatch.rs (125 lines) | |||
M | rust/hg-core/src/dirstate_tree/on_disk.rs (2 lines) |
Commit | Parents | Author | Summary | Date |
---|---|---|---|---|
7a076ce2b8f7 | 5045ba2a3afd | Simon Sapin | Jul 1 2021, 12:51 PM |
use crate::DirstateParents; | use crate::DirstateParents; | ||||
use crate::DirstateStatus; | use crate::DirstateStatus; | ||||
use crate::EntryState; | use crate::EntryState; | ||||
use crate::PatternFileWarning; | use crate::PatternFileWarning; | ||||
use crate::StateMapIter; | use crate::StateMapIter; | ||||
use crate::StatusError; | use crate::StatusError; | ||||
use crate::StatusOptions; | 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 { | pub trait DirstateMapMethods { | ||||
/// Remove information about all files in this map | |||||
fn clear(&mut self); | 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( | fn add_file( | ||||
&mut self, | &mut self, | ||||
filename: &HgPath, | filename: &HgPath, | ||||
old_state: EntryState, | old_state: EntryState, | ||||
entry: DirstateEntry, | entry: DirstateEntry, | ||||
) -> Result<(), DirstateError>; | ) -> 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( | fn remove_file( | ||||
&mut self, | &mut self, | ||||
filename: &HgPath, | filename: &HgPath, | ||||
old_state: EntryState, | old_state: EntryState, | ||||
size: i32, | size: i32, | ||||
) -> Result<(), DirstateError>; | ) -> 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( | fn drop_file( | ||||
&mut self, | &mut self, | ||||
filename: &HgPath, | filename: &HgPath, | ||||
old_state: EntryState, | old_state: EntryState, | ||||
) -> Result<bool, DirstateError>; | ) -> 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( | fn clear_ambiguous_times( | ||||
&mut self, | &mut self, | ||||
filenames: Vec<HgPathBuf>, | filenames: Vec<HgPathBuf>, | ||||
now: i32, | now: i32, | ||||
) -> Result<(), DirstateV2ParseError>; | ) -> 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( | fn non_normal_entries_contains( | ||||
&mut self, | &mut self, | ||||
key: &HgPath, | key: &HgPath, | ||||
) -> Result<bool, DirstateV2ParseError>; | ) -> 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); | 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( | fn non_normal_or_other_parent_paths( | ||||
&mut self, | &mut self, | ||||
) -> Box<dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + '_>; | ) -> 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); | 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( | fn iter_non_normal_paths( | ||||
&mut self, | &mut self, | ||||
) -> Box< | ) -> Box< | ||||
dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_, | 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( | fn iter_non_normal_paths_panic( | ||||
&self, | &self, | ||||
) -> Box< | ) -> Box< | ||||
dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_, | 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( | fn iter_other_parent_paths( | ||||
&mut self, | &mut self, | ||||
) -> Box< | ) -> Box< | ||||
dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_, | 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( | fn has_tracked_dir( | ||||
&mut self, | &mut self, | ||||
directory: &HgPath, | directory: &HgPath, | ||||
) -> Result<bool, DirstateError>; | ) -> 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>; | 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( | fn pack_v1( | ||||
&mut self, | &mut self, | ||||
parents: DirstateParents, | parents: DirstateParents, | ||||
now: Timestamp, | now: Timestamp, | ||||
) -> Result<Vec<u8>, DirstateError>; | ) -> 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( | fn pack_v2( | ||||
&mut self, | &mut self, | ||||
parents: DirstateParents, | parents: DirstateParents, | ||||
now: Timestamp, | now: Timestamp, | ||||
) -> Result<Vec<u8>, DirstateError>; | ) -> Result<Vec<u8>, DirstateError>; | ||||
fn set_all_dirs(&mut self) -> Result<(), DirstateError>; | fn set_all_dirs(&mut self) -> Result<(), DirstateError>; | ||||
fn set_dirs(&mut self) -> Result<(), DirstateError>; | 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>( | fn status<'a>( | ||||
&'a mut self, | &'a mut self, | ||||
matcher: &'a (dyn Matcher + Sync), | matcher: &'a (dyn Matcher + Sync), | ||||
root_dir: PathBuf, | root_dir: PathBuf, | ||||
ignore_files: Vec<PathBuf>, | ignore_files: Vec<PathBuf>, | ||||
options: StatusOptions, | options: StatusOptions, | ||||
) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>; | ) -> 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; | 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<'_>; | fn copy_map_iter(&self) -> CopyMapIter<'_>; | ||||
/// Returns whether the givef file has a copy source. | |||||
fn copy_map_contains_key( | fn copy_map_contains_key( | ||||
&self, | &self, | ||||
key: &HgPath, | key: &HgPath, | ||||
) -> Result<bool, DirstateV2ParseError>; | ) -> Result<bool, DirstateV2ParseError>; | ||||
/// Returns the copy source for the given file. | |||||
fn copy_map_get( | fn copy_map_get( | ||||
&self, | &self, | ||||
key: &HgPath, | key: &HgPath, | ||||
) -> Result<Option<&HgPath>, DirstateV2ParseError>; | ) -> Result<Option<&HgPath>, DirstateV2ParseError>; | ||||
/// Removes the recorded copy source if any for the given file, and returns | |||||
/// it. | |||||
fn copy_map_remove( | fn copy_map_remove( | ||||
&mut self, | &mut self, | ||||
key: &HgPath, | key: &HgPath, | ||||
) -> Result<Option<HgPathBuf>, DirstateV2ParseError>; | ) -> Result<Option<HgPathBuf>, DirstateV2ParseError>; | ||||
/// Set the given `value` copy source for the given `key` file. | |||||
fn copy_map_insert( | fn copy_map_insert( | ||||
&mut self, | &mut self, | ||||
key: HgPathBuf, | key: HgPathBuf, | ||||
value: HgPathBuf, | value: HgPathBuf, | ||||
) -> Result<Option<HgPathBuf>, DirstateV2ParseError>; | ) -> Result<Option<HgPathBuf>, DirstateV2ParseError>; | ||||
/// Returns the number of files that have an entry. | |||||
fn len(&self) -> usize; | fn len(&self) -> usize; | ||||
/// Returns whether the given file has an entry. | |||||
fn contains_key(&self, key: &HgPath) | fn contains_key(&self, key: &HgPath) | ||||
-> Result<bool, DirstateV2ParseError>; | -> Result<bool, DirstateV2ParseError>; | ||||
/// Returns the entry, if any, for the given file. | |||||
fn get( | fn get( | ||||
&self, | &self, | ||||
key: &HgPath, | key: &HgPath, | ||||
) -> Result<Option<DirstateEntry>, DirstateV2ParseError>; | ) -> 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<'_>; | 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( | fn iter_directories( | ||||
&self, | &self, | ||||
) -> Box< | ) -> Box< | ||||
dyn Iterator< | dyn Iterator< | ||||
Item = Result< | Item = Result< | ||||
(&HgPath, Option<Timestamp>), | (&HgPath, Option<Timestamp>), | ||||
DirstateV2ParseError, | DirstateV2ParseError, | ||||
>, | >, |
/// In bytes from `self.full_path.start` | /// In bytes from `self.full_path.start` | ||||
base_name_start: Size, | base_name_start: Size, | ||||
copy_source: OptPathSlice, | copy_source: OptPathSlice, | ||||
children: ChildNodes, | children: ChildNodes, | ||||
pub(super) tracked_descendants_count: Size, | 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. | /// * A null byte: `data` is not used. | ||||
/// | /// | ||||
/// * A `n`, `a`, `r`, or `m` ASCII byte: `state` and `data` together | /// * A `n`, `a`, `r`, or `m` ASCII byte: `state` and `data` together | ||||
/// represent a dirstate entry like in the v1 format. | /// represent a dirstate entry like in the v1 format. | ||||
/// | /// | ||||
/// * A `d` ASCII byte: the bytes of `data` should instead be interpreted | /// * A `d` ASCII byte: the bytes of `data` should instead be interpreted | ||||
/// as the `Timestamp` for the mtime of a cached directory. | /// as the `Timestamp` for the mtime of a cached directory. |