This will help reduce code and footgun potential for simpler callers.
Details
Details
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Branch
- default
- Lint
No Linters Available - Unit
No Unit Test Coverage
( )
| hg-reviewers |
This will help reduce code and footgun potential for simpler callers.
| No Linters Available |
| No Unit Test Coverage |
| Path | Packages | |||
|---|---|---|---|---|
| M | rust/hg-core/src/dirstate_tree/dirstate_map.rs (76 lines) |
| Commit | Parents | Author | Summary | Date |
|---|---|---|---|---|
| c4dcac589c88 | e96b9ba2f8c3 | Raphaël Gomès | Fri, Apr 8, 11:55 AM |
| Status | Author | Revision | |
|---|---|---|---|
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare | ||
| Needs Review | Alphare |
| } else { | } else { | ||||
| return Ok(None); | return Ok(None); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /// Returns a mutable reference to the node at `path` if it exists | /// Returns a mutable reference to the node at `path` if it exists | ||||
| /// | /// | ||||
| /// `each_ancestor` is a callback that is called for each ancestor node | |||||
| /// when descending the tree. It is used to keep the different counters | |||||
| /// of the `DirstateMap` up-to-date. | |||||
| fn get_node_mut<'tree>( | |||||
| &'tree mut self, | |||||
| path: &HgPath, | |||||
| each_ancestor: impl FnMut(&mut Node), | |||||
| ) -> Result<Option<&'tree mut Node<'on_disk>>, DirstateV2ParseError> { | |||||
| Self::get_node_mut_inner( | |||||
| self.on_disk, | |||||
| &mut self.unreachable_bytes, | |||||
| &mut self.root, | |||||
| path, | |||||
| each_ancestor, | |||||
| ) | |||||
| } | |||||
| /// Lower-level version of `get_node_mut`. | |||||
| /// | |||||
| /// This takes `root` instead of `&mut self` so that callers can mutate | /// This takes `root` instead of `&mut self` so that callers can mutate | ||||
| /// other fields while the returned borrow is still valid. | /// other fields while the returned borrow is still valid. | ||||
| /// | /// | ||||
| /// `each_ancestor` is a callback that is called for each ancestor node | /// `each_ancestor` is a callback that is called for each ancestor node | ||||
| /// when descending the tree. It is used to keep the different counters | /// when descending the tree. It is used to keep the different counters | ||||
| /// of the `DirstateMap` up-to-date. | /// of the `DirstateMap` up-to-date. | ||||
| fn get_node_mut<'tree>( | fn get_node_mut_inner<'tree>( | ||||
| on_disk: &'on_disk [u8], | on_disk: &'on_disk [u8], | ||||
| unreachable_bytes: &mut u32, | unreachable_bytes: &mut u32, | ||||
| root: &'tree mut ChildNodes<'on_disk>, | root: &'tree mut ChildNodes<'on_disk>, | ||||
| path: &HgPath, | path: &HgPath, | ||||
| mut each_ancestor: impl FnMut(&mut Node), | mut each_ancestor: impl FnMut(&mut Node), | ||||
| ) -> Result<Option<&'tree mut Node<'on_disk>>, DirstateV2ParseError> { | ) -> Result<Option<&'tree mut Node<'on_disk>>, DirstateV2ParseError> { | ||||
| let mut children = root; | let mut children = root; | ||||
| let mut components = path.components(); | let mut components = path.components(); | ||||
| /// # Panics | /// # Panics | ||||
| /// | /// | ||||
| /// Panics if the node does not exist. | /// Panics if the node does not exist. | ||||
| fn set_untracked( | fn set_untracked( | ||||
| &mut self, | &mut self, | ||||
| filename: &HgPath, | filename: &HgPath, | ||||
| old_entry: DirstateEntry, | old_entry: DirstateEntry, | ||||
| ) -> Result<(), DirstateV2ParseError> { | ) -> Result<(), DirstateV2ParseError> { | ||||
| let node = DirstateMap::get_node_mut( | let node = self | ||||
| self.on_disk, | .get_node_mut(filename, |ancestor| { | ||||
| &mut self.unreachable_bytes, | |||||
| &mut self.root, | |||||
| filename, | |||||
| |ancestor| { | |||||
| ancestor.tracked_descendants_count = ancestor | ancestor.tracked_descendants_count = ancestor | ||||
| .tracked_descendants_count | .tracked_descendants_count | ||||
| .checked_sub(1) | .checked_sub(1) | ||||
| .expect("tracked_descendants_count should be >= 0"); | .expect("tracked_descendants_count should be >= 0"); | ||||
| }, | })? | ||||
| )? | |||||
| .expect("node should exist"); | .expect("node should exist"); | ||||
| let mut new_entry = old_entry.clone(); | let mut new_entry = old_entry.clone(); | ||||
| new_entry.set_untracked(); | new_entry.set_untracked(); | ||||
| node.data = NodeData::Entry(new_entry); | node.data = NodeData::Entry(new_entry); | ||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| /// Set a node as clean in the dirstate. | /// Set a node as clean in the dirstate. | ||||
| /// | /// | ||||
| /// It is the responsibility of the caller to remove the copy source. | /// It is the responsibility of the caller to remove the copy source. | ||||
| /// | /// | ||||
| /// # Panics | /// # Panics | ||||
| /// | /// | ||||
| /// Panics if the node does not exist. | /// Panics if the node does not exist. | ||||
| fn set_clean( | fn set_clean( | ||||
| &mut self, | &mut self, | ||||
| filename: &HgPath, | filename: &HgPath, | ||||
| old_entry: DirstateEntry, | old_entry: DirstateEntry, | ||||
| mode: u32, | mode: u32, | ||||
| size: u32, | size: u32, | ||||
| mtime: TruncatedTimestamp, | mtime: TruncatedTimestamp, | ||||
| ) -> Result<(), DirstateError> { | ) -> Result<(), DirstateError> { | ||||
| let node = DirstateMap::get_node_mut( | let node = self | ||||
| self.on_disk, | .get_node_mut(filename, |ancestor| { | ||||
| &mut self.unreachable_bytes, | |||||
| &mut self.root, | |||||
| filename, | |||||
| |ancestor| { | |||||
| if !old_entry.tracked() { | if !old_entry.tracked() { | ||||
| ancestor.tracked_descendants_count += 1; | ancestor.tracked_descendants_count += 1; | ||||
| } | } | ||||
| }, | })? | ||||
| )? | |||||
| .expect("node should exist"); | .expect("node should exist"); | ||||
| let mut new_entry = old_entry.clone(); | let mut new_entry = old_entry.clone(); | ||||
| new_entry.set_clean(mode, size, mtime); | new_entry.set_clean(mode, size, mtime); | ||||
| node.data = NodeData::Entry(new_entry); | node.data = NodeData::Entry(new_entry); | ||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| /// Set a node as possibly dirty in the dirstate. | /// Set a node as possibly dirty in the dirstate. | ||||
| /// | /// | ||||
| /// # Panics | /// # Panics | ||||
| /// | /// | ||||
| /// Panics if the node does not exist. | /// Panics if the node does not exist. | ||||
| fn set_possibly_dirty( | fn set_possibly_dirty( | ||||
| &mut self, | &mut self, | ||||
| filename: &HgPath, | filename: &HgPath, | ||||
| ) -> Result<(), DirstateError> { | ) -> Result<(), DirstateError> { | ||||
| let node = DirstateMap::get_node_mut( | let node = self | ||||
| self.on_disk, | .get_node_mut(filename, |_ancestor| {})? | ||||
| &mut self.unreachable_bytes, | |||||
| &mut self.root, | |||||
| filename, | |||||
| |_ancestor| {}, | |||||
| )? | |||||
| .expect("node should exist"); | .expect("node should exist"); | ||||
| let entry = node.data.as_entry_mut().expect("entry should exist"); | let entry = node.data.as_entry_mut().expect("entry should exist"); | ||||
| entry.set_possibly_dirty(); | entry.set_possibly_dirty(); | ||||
| node.data = NodeData::Entry(*entry); | node.data = NodeData::Entry(*entry); | ||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| /// Clears the cached mtime for the (potential) folder at `path`. | /// Clears the cached mtime for the (potential) folder at `path`. | ||||
| pub(super) fn clear_cached_mtime( | pub(super) fn clear_cached_mtime( | ||||
| &mut self, | &mut self, | ||||
| path: &HgPath, | path: &HgPath, | ||||
| ) -> Result<(), DirstateV2ParseError> { | ) -> Result<(), DirstateV2ParseError> { | ||||
| let node = match DirstateMap::get_node_mut( | let node = match self.get_node_mut(path, |_ancestor| {})? { | ||||
| self.on_disk, | |||||
| &mut self.unreachable_bytes, | |||||
| &mut self.root, | |||||
| path, | |||||
| |_ancestor| {}, | |||||
| )? { | |||||
| Some(node) => node, | Some(node) => node, | ||||
| None => return Ok(()), | None => return Ok(()), | ||||
| }; | }; | ||||
| if let NodeData::CachedDirectory { .. } = &node.data { | if let NodeData::CachedDirectory { .. } = &node.data { | ||||
| node.data = NodeData::None | node.data = NodeData::None | ||||
| } | } | ||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| /// Sets the cached mtime for the (potential) folder at `path`. | /// Sets the cached mtime for the (potential) folder at `path`. | ||||
| pub(super) fn set_cached_mtime( | pub(super) fn set_cached_mtime( | ||||
| &mut self, | &mut self, | ||||
| path: &HgPath, | path: &HgPath, | ||||
| mtime: TruncatedTimestamp, | mtime: TruncatedTimestamp, | ||||
| ) -> Result<(), DirstateV2ParseError> { | ) -> Result<(), DirstateV2ParseError> { | ||||
| let node = match DirstateMap::get_node_mut( | let node = match self.get_node_mut(path, |_ancestor| {})? { | ||||
| self.on_disk, | |||||
| &mut self.unreachable_bytes, | |||||
| &mut self.root, | |||||
| path, | |||||
| |_ancestor| {}, | |||||
| )? { | |||||
| Some(node) => node, | Some(node) => node, | ||||
| None => return Ok(()), | None => return Ok(()), | ||||
| }; | }; | ||||
| match &node.data { | match &node.data { | ||||
| NodeData::Entry(_) => {} // Don’t overwrite an entry | NodeData::Entry(_) => {} // Don’t overwrite an entry | ||||
| NodeData::CachedDirectory { .. } | NodeData::None => { | NodeData::CachedDirectory { .. } | NodeData::None => { | ||||
| node.data = NodeData::CachedDirectory { mtime } | node.data = NodeData::CachedDirectory { mtime } | ||||
| } | } | ||||
| pub fn copy_map_remove( | pub fn copy_map_remove( | ||||
| &mut self, | &mut self, | ||||
| key: &HgPath, | key: &HgPath, | ||||
| ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { | ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { | ||||
| self.with_dmap_mut(|map| { | self.with_dmap_mut(|map| { | ||||
| let count = &mut map.nodes_with_copy_source_count; | let count = &mut map.nodes_with_copy_source_count; | ||||
| let unreachable_bytes = &mut map.unreachable_bytes; | let unreachable_bytes = &mut map.unreachable_bytes; | ||||
| Ok(DirstateMap::get_node_mut( | Ok(DirstateMap::get_node_mut_inner( | ||||
| map.on_disk, | map.on_disk, | ||||
| unreachable_bytes, | unreachable_bytes, | ||||
| &mut map.root, | &mut map.root, | ||||
| key, | key, | ||||
| |_ancestor| {}, | |_ancestor| {}, | ||||
| )? | )? | ||||
| .and_then(|node| { | .and_then(|node| { | ||||
| if let Some(source) = &node.copy_source { | if let Some(source) = &node.copy_source { | ||||