Mercurial > public > mercurial-scm > hg-stable
diff rust/hg-core/src/dirstate/entry.rs @ 48271:269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Keep integer seconds since the Unix epoch,
together with integer nanoseconds in the `0 <= n < 1e9` range.
For now, nanoseconds are still always zero.
This commit is about data structure changes.
Differential Revision: https://phab.mercurial-scm.org/D11684
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Mon, 18 Oct 2021 11:23:07 +0200 |
parents | 84f6b0c41b90 |
children | 68bb472aee9c |
line wrap: on
line diff
--- a/rust/hg-core/src/dirstate/entry.rs Tue Oct 19 21:03:13 2021 +0200 +++ b/rust/hg-core/src/dirstate/entry.rs Mon Oct 18 11:23:07 2021 +0200 @@ -14,14 +14,15 @@ Merged, } -/// The C implementation uses all signed types. This will be an issue -/// either when 4GB+ source files are commonplace or in 2038, whichever -/// comes first. -#[derive(Debug, PartialEq, Copy, Clone)] +/// `size` and `mtime.seconds` are truncated to 31 bits. +/// +/// TODO: double-check status algorithm correctness for files +/// larger than 2 GiB or modified after 2038. +#[derive(Debug, Copy, Clone)] pub struct DirstateEntry { pub(crate) flags: Flags, mode_size: Option<(u32, u32)>, - mtime: Option<u32>, + mtime: Option<TruncatedTimestamp>, } bitflags! { @@ -37,7 +38,7 @@ } /// A Unix timestamp with nanoseconds precision -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub struct TruncatedTimestamp { truncated_seconds: u32, /// Always in the `0 .. 1_000_000_000` range. @@ -90,6 +91,11 @@ } } + pub fn to_integer_second(mut self) -> Self { + self.nanoseconds = 0; + self + } + /// The lower 31 bits of the number of seconds since the epoch. pub fn truncated_seconds(&self) -> u32 { self.truncated_seconds @@ -182,7 +188,7 @@ p1_tracked: bool, p2_info: bool, mode_size: Option<(u32, u32)>, - mtime: Option<u32>, + mtime: Option<TruncatedTimestamp>, fallback_exec: Option<bool>, fallback_symlink: Option<bool>, ) -> Self { @@ -191,9 +197,6 @@ 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); @@ -252,6 +255,9 @@ let mode = u32::try_from(mode).unwrap(); let size = u32::try_from(size).unwrap(); let mtime = u32::try_from(mtime).unwrap(); + let mtime = + TruncatedTimestamp::from_already_truncated(mtime, 0) + .unwrap(); Self { flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED, mode_size: Some((mode, size)), @@ -344,7 +350,7 @@ bool, bool, Option<(u32, u32)>, - Option<u32>, + Option<TruncatedTimestamp>, Option<bool>, Option<bool>, ) { @@ -429,7 +435,7 @@ } else if !self.flags.contains(Flags::P1_TRACKED) { MTIME_UNSET } else if let Some(mtime) = self.mtime { - i32::try_from(mtime).unwrap() + i32::try_from(mtime.truncated_seconds()).unwrap() } else { MTIME_UNSET } @@ -501,6 +507,10 @@ } } + pub fn truncated_mtime(&self) -> Option<TruncatedTimestamp> { + self.mtime + } + pub fn drop_merge_data(&mut self) { if self.flags.contains(Flags::P2_INFO) { self.flags.remove(Flags::P2_INFO); @@ -513,9 +523,13 @@ self.mtime = None } - pub fn set_clean(&mut self, mode: u32, size: u32, mtime: u32) { + pub fn set_clean( + &mut self, + mode: u32, + size: u32, + mtime: TruncatedTimestamp, + ) { 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); @@ -577,8 +591,13 @@ } /// True if the stored mtime would be ambiguous with the current time - pub fn need_delay(&self, now: i32) -> bool { - self.state() == EntryState::Normal && self.mtime() == now + pub fn need_delay(&self, now: TruncatedTimestamp) -> bool { + if let Some(mtime) = self.mtime { + self.state() == EntryState::Normal + && mtime.truncated_seconds() == now.truncated_seconds() + } else { + false + } } }