diff --git a/rust/hg-core/src/dirstate_tree/dirstate_map.rs b/rust/hg-core/src/dirstate_tree/dirstate_map.rs --- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs +++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs @@ -21,6 +21,7 @@ use crate::utils::hg_path::{HgPath, HgPathBuf}; use crate::DirstateEntry; use crate::DirstateError; +use crate::DirstateMapError; use crate::DirstateParents; use crate::DirstateStatus; use crate::EntryState; @@ -764,6 +765,32 @@ Ok(()) } + fn set_clean( + &mut self, + filename: &HgPath, + old_entry: DirstateEntry, + mode: u32, + size: u32, + mtime: TruncatedTimestamp, + ) -> Result<(), DirstateError> { + let node = Self::get_or_insert_node( + self.on_disk, + &mut self.unreachable_bytes, + &mut self.root, + filename, + WithBasename::to_cow_owned, + |ancestor| { + if !old_entry.tracked() { + ancestor.tracked_descendants_count += 1; + } + }, + )?; + let mut new_entry = old_entry.clone(); + new_entry.set_clean(mode, size, mtime); + node.data = NodeData::Entry(new_entry); + Ok(()) + } + fn iter_nodes<'tree>( &'tree self, ) -> impl Iterator< @@ -881,6 +908,27 @@ self.with_dmap_mut(|map| map.set_tracked(filename, old_entry_opt)) } + pub fn set_clean( + &mut self, + filename: &HgPath, + mode: u32, + size: u32, + mtime: TruncatedTimestamp, + ) -> Result<(), DirstateError> { + let old_entry = match self.get(filename)? { + None => { + return Err( + DirstateMapError::PathNotFound(filename.into()).into() + ) + } + Some(e) => e, + }; + self.copy_map_remove(filename)?; + self.with_dmap_mut(|map| { + map.set_clean(filename, old_entry, mode, size, mtime) + }) + } + pub fn reset_state( &mut self, filename: &HgPath, diff --git a/rust/hg-cpython/src/dirstate/dirstate_map.rs b/rust/hg-cpython/src/dirstate/dirstate_map.rs --- a/rust/hg-cpython/src/dirstate/dirstate_map.rs +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs @@ -142,6 +142,28 @@ Ok(was_tracked.to_py_object(py)) } + def set_clean( + &self, + f: PyObject, + mode: u32, + size: u32, + mtime: (i64, u32, bool) + ) -> PyResult { + let (mtime_s, mtime_ns, second_ambiguous) = mtime; + let timestamp = TruncatedTimestamp::new_truncate( + mtime_s, mtime_ns, second_ambiguous + ); + let bytes = f.extract::(py)?; + let path = HgPath::new(bytes.data(py)); + let res = self.inner(py).borrow_mut().set_clean( + path, mode, size, timestamp, + ); + res.or_else(|_| { + Err(PyErr::new::(py, "Dirstate error".to_string())) + })?; + Ok(PyNone) + } + def reset_state( &self, f: PyObject,