diff --git a/rust/hg-core/src/dirstate/entry.rs b/rust/hg-core/src/dirstate/entry.rs --- a/rust/hg-core/src/dirstate/entry.rs +++ b/rust/hg-core/src/dirstate/entry.rs @@ -18,8 +18,8 @@ #[derive(Debug, PartialEq, Copy, Clone)] pub struct DirstateEntry { pub(crate) flags: Flags, - mode_size: Option<(i32, i32)>, - mtime: Option, + mode_size: Option<(u32, u32)>, + mtime: Option, } bitflags! { @@ -153,9 +153,17 @@ wdir_tracked: bool, p1_tracked: bool, p2_info: bool, - mode_size: Option<(i32, i32)>, - mtime: Option, + mode_size: Option<(u32, u32)>, + mtime: Option, ) -> Self { + if let Some((mode, size)) = mode_size { + // TODO: return an error for out of range values? + assert!(mode & !RANGE_MASK_31BIT == 0); + assert!(size & !RANGE_MASK_31BIT == 0); + } + if let Some(mtime) = mtime { + assert!(mtime & !RANGE_MASK_31BIT == 0); + } let mut flags = Flags::empty(); flags.set(Flags::WDIR_TRACKED, wdir_tracked); flags.set(Flags::P1_TRACKED, p1_tracked); @@ -189,12 +197,19 @@ mtime: None, } } else if mtime == MTIME_UNSET { + // TODO: return an error for negative values? + let mode = u32::try_from(mode).unwrap(); + let size = u32::try_from(size).unwrap(); Self { flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED, mode_size: Some((mode, size)), mtime: None, } } else { + // TODO: return an error for negative values? + let mode = u32::try_from(mode).unwrap(); + let size = u32::try_from(size).unwrap(); + let mtime = u32::try_from(mtime).unwrap(); Self { flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED, mode_size: Some((mode, size)), @@ -282,7 +297,7 @@ /// Returns `(wdir_tracked, p1_tracked, p2_info, mode_size, mtime)` pub(crate) fn v2_data( &self, - ) -> (bool, bool, bool, Option<(i32, i32)>, Option) { + ) -> (bool, bool, bool, Option<(u32, u32)>, Option) { if !self.any_tracked() { // TODO: return an Option instead? panic!("Accessing v1_state of an untracked DirstateEntry") @@ -316,7 +331,7 @@ fn v1_mode(&self) -> i32 { if let Some((mode, _size)) = self.mode_size { - mode + i32::try_from(mode).unwrap() } else { 0 } @@ -338,7 +353,7 @@ } else if self.added() { SIZE_NON_NORMAL } else if let Some((_mode, size)) = self.mode_size { - size + i32::try_from(size).unwrap() } else { SIZE_NON_NORMAL } @@ -355,8 +370,10 @@ MTIME_UNSET } else if !self.flags.contains(Flags::P1_TRACKED) { MTIME_UNSET + } else if let Some(mtime) = self.mtime { + i32::try_from(mtime).unwrap() } else { - self.mtime.unwrap_or(MTIME_UNSET) + MTIME_UNSET } } @@ -392,7 +409,9 @@ self.mtime = None } - pub fn set_clean(&mut self, mode: i32, size: i32, mtime: i32) { + pub fn set_clean(&mut self, mode: u32, size: u32, mtime: u32) { + let size = size & RANGE_MASK_31BIT; + let mtime = mtime & RANGE_MASK_31BIT; self.flags.insert(Flags::WDIR_TRACKED | Flags::P1_TRACKED); self.mode_size = Some((mode, size)); self.mtime = Some(mtime); diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs b/rust/hg-core/src/dirstate_tree/on_disk.rs --- a/rust/hg-core/src/dirstate_tree/on_disk.rs +++ b/rust/hg-core/src/dirstate_tree/on_disk.rs @@ -11,7 +11,7 @@ use crate::DirstateError; use crate::DirstateParents; use bitflags::bitflags; -use bytes_cast::unaligned::{I32Be, U16Be, U32Be}; +use bytes_cast::unaligned::{U16Be, U32Be}; use bytes_cast::BytesCast; use format_bytes::format_bytes; use std::borrow::Cow; @@ -113,9 +113,9 @@ #[derive(BytesCast, Copy, Clone, Debug)] #[repr(C)] struct Entry { - mode: I32Be, - size: I32Be, - mtime: I32Be, + mode: U32Be, + size: U32Be, + mtime: U32Be, } /// Duration since the Unix epoch diff --git a/rust/hg-cpython/src/dirstate/item.rs b/rust/hg-cpython/src/dirstate/item.rs --- a/rust/hg-cpython/src/dirstate/item.rs +++ b/rust/hg-cpython/src/dirstate/item.rs @@ -21,7 +21,7 @@ p2_info: bool = false, has_meaningful_data: bool = true, has_meaningful_mtime: bool = true, - parentfiledata: Option<(i32, i32, i32)> = None, + parentfiledata: Option<(u32, u32, u32)> = None, ) -> PyResult { let mut mode_size_opt = None; @@ -145,9 +145,9 @@ def set_clean( &self, - mode: i32, - size: i32, - mtime: i32, + mode: u32, + size: u32, + mtime: u32, ) -> PyResult { self.update(py, |entry| entry.set_clean(mode, size, mtime)); Ok(PyNone)