rust-dirstatemap: add `set_tracked` method
authorRaphaël Gomès <rgomes@octobus.net>
Wed, 23 Mar 2022 15:18:12 +0100
changeset 49097 791430b0b2d2
parent 49096 07ec9f4f24bf
child 49098 55c158a33fa5
rust-dirstatemap: add `set_tracked` method This is the new dirstate API that has already been moved to in Python. It will be used in place of the old `addfile`/`removefile` one. Differential Revision: https://phab.mercurial-scm.org/D12495
rust/hg-core/src/dirstate/entry.rs
rust/hg-core/src/dirstate_tree/dirstate_map.rs
--- a/rust/hg-core/src/dirstate/entry.rs	Tue Apr 12 23:15:25 2022 -0700
+++ b/rust/hg-core/src/dirstate/entry.rs	Wed Mar 23 15:18:12 2022 +0100
@@ -367,6 +367,10 @@
         Self::from_v1_data(EntryState::Removed, 0, size, 0)
     }
 
+    pub fn new_tracked() -> Self {
+        Self::from_v2_data(true, false, false, None, None, None, None)
+    }
+
     pub fn tracked(&self) -> bool {
         self.flags.contains(Flags::WDIR_TRACKED)
     }
--- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs	Tue Apr 12 23:15:25 2022 -0700
+++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs	Wed Mar 23 15:18:12 2022 +0100
@@ -606,6 +606,52 @@
         }
     }
 
+    fn set_tracked(
+        &mut self,
+        filename: &HgPath,
+        old_entry_opt: Option<DirstateEntry>,
+    ) -> Result<bool, DirstateV2ParseError> {
+        let was_tracked = old_entry_opt.map_or(false, |e| e.tracked());
+        let had_entry = old_entry_opt.is_some();
+        let tracked_count_increment = if was_tracked { 0 } else { 1 };
+        let mut new = 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;
+                }
+
+                ancestor.tracked_descendants_count += tracked_count_increment;
+            },
+        )?;
+        let new_entry = if let Some(old_entry) = old_entry_opt {
+            let mut e = old_entry.clone();
+            if e.tracked() {
+                // XXX
+                // This is probably overkill for more case, but we need this to
+                // fully replace the `normallookup` call with `set_tracked`
+                // one. Consider smoothing this in the future.
+                e.set_possibly_dirty();
+            } else {
+                new = true;
+                e.set_tracked();
+            }
+            e
+        } else {
+            self.nodes_with_entry_count += 1;
+            new = true;
+            DirstateEntry::new_tracked()
+        };
+        node.data = NodeData::Entry(new_entry);
+        Ok(new)
+    }
+
     fn add_or_remove_file(
         &mut self,
         path: &HgPath,
@@ -758,6 +804,14 @@
         })
     }
 
+    pub fn set_tracked(
+        &mut self,
+        filename: &HgPath,
+    ) -> Result<bool, DirstateV2ParseError> {
+        let old_entry_opt = self.get(filename)?;
+        self.with_dmap_mut(|map| map.set_tracked(filename, old_entry_opt))
+    }
+
     pub fn remove_file(
         &mut self,
         filename: &HgPath,