rust/hg-core/src/dirstate_tree/dirstate_map.rs
changeset 49101 dd0430434ce9
parent 49097 791430b0b2d2
child 49104 b5c2aca84618
--- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs	Wed Mar 23 17:38:59 2022 +0100
+++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs	Wed Mar 23 17:27:58 2022 +0100
@@ -11,6 +11,8 @@
 use crate::dirstate::parsers::packed_entry_size;
 use crate::dirstate::parsers::parse_dirstate_entries;
 use crate::dirstate::CopyMapIter;
+use crate::dirstate::DirstateV2Data;
+use crate::dirstate::ParentFileData;
 use crate::dirstate::StateMapIter;
 use crate::dirstate::TruncatedTimestamp;
 use crate::dirstate::SIZE_FROM_OTHER_PARENT;
@@ -606,6 +608,73 @@
         }
     }
 
+    fn reset_state(
+        &mut self,
+        filename: &HgPath,
+        old_entry_opt: Option<DirstateEntry>,
+        wc_tracked: bool,
+        p1_tracked: bool,
+        p2_info: bool,
+        has_meaningful_mtime: bool,
+        parent_file_data_opt: Option<ParentFileData>,
+    ) -> Result<(), DirstateError> {
+        let (had_entry, was_tracked) = match old_entry_opt {
+            Some(old_entry) => (true, old_entry.tracked()),
+            None => (false, false),
+        };
+        let node = Self::get_or_insert_node(
+            self.on_disk,
+            &mut self.unreachable_bytes,
+            &mut self.root,
+            filename,
+            WithBasename::to_cow_owned,
+            |ancestor| {
+                if !had_entry {
+                    ancestor.descendants_with_entry_count += 1;
+                }
+                if was_tracked {
+                    if !wc_tracked {
+                        ancestor.tracked_descendants_count = ancestor
+                            .tracked_descendants_count
+                            .checked_sub(1)
+                            .expect("tracked count to be >= 0");
+                    }
+                } else {
+                    if wc_tracked {
+                        ancestor.tracked_descendants_count += 1;
+                    }
+                }
+            },
+        )?;
+
+        let v2_data = if let Some(parent_file_data) = parent_file_data_opt {
+            DirstateV2Data {
+                wc_tracked,
+                p1_tracked,
+                p2_info,
+                mode_size: parent_file_data.mode_size,
+                mtime: if has_meaningful_mtime {
+                    parent_file_data.mtime
+                } else {
+                    None
+                },
+                ..Default::default()
+            }
+        } else {
+            DirstateV2Data {
+                wc_tracked,
+                p1_tracked,
+                p2_info,
+                ..Default::default()
+            }
+        };
+        if !had_entry {
+            self.nodes_with_entry_count += 1;
+        }
+        node.data = NodeData::Entry(DirstateEntry::from_v2_data(v2_data));
+        Ok(())
+    }
+
     fn set_tracked(
         &mut self,
         filename: &HgPath,
@@ -812,6 +881,34 @@
         self.with_dmap_mut(|map| map.set_tracked(filename, old_entry_opt))
     }
 
+    pub fn reset_state(
+        &mut self,
+        filename: &HgPath,
+        wc_tracked: bool,
+        p1_tracked: bool,
+        p2_info: bool,
+        has_meaningful_mtime: bool,
+        parent_file_data_opt: Option<ParentFileData>,
+    ) -> Result<(), DirstateError> {
+        if !(p1_tracked || p2_info || wc_tracked) {
+            self.drop_entry_and_copy_source(filename)?;
+            return Ok(());
+        }
+        self.copy_map_remove(filename)?;
+        let old_entry_opt = self.get(filename)?;
+        self.with_dmap_mut(|map| {
+            map.reset_state(
+                filename,
+                old_entry_opt,
+                wc_tracked,
+                p1_tracked,
+                p2_info,
+                has_meaningful_mtime,
+                parent_file_data_opt,
+            )
+        })
+    }
+
     pub fn remove_file(
         &mut self,
         filename: &HgPath,