rust: Move DirstateEntry to its own module
… and RawEntry to the dirstate::parsers module, the only one that uses it.
Differential Revision: https://phab.mercurial-scm.org/D11457
--- a/rust/hg-core/src/dirstate.rs Mon Sep 20 14:21:18 2021 -0400
+++ b/rust/hg-core/src/dirstate.rs Fri Sep 17 12:42:24 2021 +0200
@@ -6,19 +6,20 @@
// GNU General Public License version 2 or any later version.
use crate::dirstate_tree::on_disk::DirstateV2ParseError;
-use crate::errors::HgError;
use crate::revlog::node::NULL_NODE;
use crate::revlog::Node;
use crate::utils::hg_path::{HgPath, HgPathBuf};
use crate::FastHashMap;
-use bytes_cast::{unaligned, BytesCast};
-use std::convert::TryFrom;
+use bytes_cast::BytesCast;
pub mod dirs_multiset;
pub mod dirstate_map;
+pub mod entry;
pub mod parsers;
pub mod status;
+pub use self::entry::*;
+
#[derive(Debug, PartialEq, Copy, Clone, BytesCast)]
#[repr(C)]
pub struct DirstateParents {
@@ -33,68 +34,6 @@
};
}
-/// 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)]
-pub struct DirstateEntry {
- pub state: EntryState,
- pub mode: i32,
- pub mtime: i32,
- pub size: i32,
-}
-
-impl DirstateEntry {
- pub fn is_non_normal(&self) -> bool {
- self.state != EntryState::Normal || self.mtime == MTIME_UNSET
- }
-
- pub fn is_from_other_parent(&self) -> bool {
- self.state == EntryState::Normal && self.size == SIZE_FROM_OTHER_PARENT
- }
-
- // TODO: other platforms
- #[cfg(unix)]
- pub fn mode_changed(
- &self,
- filesystem_metadata: &std::fs::Metadata,
- ) -> bool {
- use std::os::unix::fs::MetadataExt;
- const EXEC_BIT_MASK: u32 = 0o100;
- let dirstate_exec_bit = (self.mode as u32) & EXEC_BIT_MASK;
- let fs_exec_bit = filesystem_metadata.mode() & EXEC_BIT_MASK;
- dirstate_exec_bit != fs_exec_bit
- }
-
- /// Returns a `(state, mode, size, mtime)` tuple as for
- /// `DirstateMapMethods::debug_iter`.
- pub fn debug_tuple(&self) -> (u8, i32, i32, i32) {
- (self.state.into(), self.mode, self.size, self.mtime)
- }
-}
-
-#[derive(BytesCast)]
-#[repr(C)]
-struct RawEntry {
- state: u8,
- mode: unaligned::I32Be,
- size: unaligned::I32Be,
- mtime: unaligned::I32Be,
- length: unaligned::I32Be,
-}
-
-pub const V1_RANGEMASK: i32 = 0x7FFFFFFF;
-
-pub const MTIME_UNSET: i32 = -1;
-
-/// A `DirstateEntry` with a size of `-2` means that it was merged from the
-/// other parent. This allows revert to pick the right status back during a
-/// merge.
-pub const SIZE_FROM_OTHER_PARENT: i32 = -2;
-/// A special value used for internal representation of special case in
-/// dirstate v1 format.
-pub const SIZE_NON_NORMAL: i32 = -1;
-
pub type StateMap = FastHashMap<HgPathBuf, DirstateEntry>;
pub type StateMapIter<'a> = Box<
dyn Iterator<
@@ -109,52 +48,3 @@
+ Send
+ 'a,
>;
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub enum EntryState {
- Normal,
- Added,
- Removed,
- Merged,
- Unknown,
-}
-
-impl EntryState {
- pub fn is_tracked(self) -> bool {
- use EntryState::*;
- match self {
- Normal | Added | Merged => true,
- Removed | Unknown => false,
- }
- }
-}
-
-impl TryFrom<u8> for EntryState {
- type Error = HgError;
-
- fn try_from(value: u8) -> Result<Self, Self::Error> {
- match value {
- b'n' => Ok(EntryState::Normal),
- b'a' => Ok(EntryState::Added),
- b'r' => Ok(EntryState::Removed),
- b'm' => Ok(EntryState::Merged),
- b'?' => Ok(EntryState::Unknown),
- _ => Err(HgError::CorruptedRepository(format!(
- "Incorrect dirstate entry state {}",
- value
- ))),
- }
- }
-}
-
-impl Into<u8> for EntryState {
- fn into(self) -> u8 {
- match self {
- EntryState::Normal => b'n',
- EntryState::Added => b'a',
- EntryState::Removed => b'r',
- EntryState::Merged => b'm',
- EntryState::Unknown => b'?',
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hg-core/src/dirstate/entry.rs Fri Sep 17 12:42:24 2021 +0200
@@ -0,0 +1,128 @@
+use crate::errors::HgError;
+use std::convert::TryFrom;
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum EntryState {
+ Normal,
+ Added,
+ Removed,
+ Merged,
+ Unknown,
+}
+
+/// 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)]
+pub struct DirstateEntry {
+ pub state: EntryState,
+ pub mode: i32,
+ pub mtime: i32,
+ pub size: i32,
+}
+
+pub const V1_RANGEMASK: i32 = 0x7FFFFFFF;
+
+pub const MTIME_UNSET: i32 = -1;
+
+/// A `DirstateEntry` with a size of `-2` means that it was merged from the
+/// other parent. This allows revert to pick the right status back during a
+/// merge.
+pub const SIZE_FROM_OTHER_PARENT: i32 = -2;
+/// A special value used for internal representation of special case in
+/// dirstate v1 format.
+pub const SIZE_NON_NORMAL: i32 = -1;
+
+impl DirstateEntry {
+ pub fn is_non_normal(&self) -> bool {
+ self.state != EntryState::Normal || self.mtime == MTIME_UNSET
+ }
+
+ pub fn is_from_other_parent(&self) -> bool {
+ self.state == EntryState::Normal && self.size == SIZE_FROM_OTHER_PARENT
+ }
+
+ // TODO: other platforms
+ #[cfg(unix)]
+ pub fn mode_changed(
+ &self,
+ filesystem_metadata: &std::fs::Metadata,
+ ) -> bool {
+ use std::os::unix::fs::MetadataExt;
+ const EXEC_BIT_MASK: u32 = 0o100;
+ let dirstate_exec_bit = (self.mode as u32) & EXEC_BIT_MASK;
+ let fs_exec_bit = filesystem_metadata.mode() & EXEC_BIT_MASK;
+ dirstate_exec_bit != fs_exec_bit
+ }
+
+ /// Returns a `(state, mode, size, mtime)` tuple as for
+ /// `DirstateMapMethods::debug_iter`.
+ pub fn debug_tuple(&self) -> (u8, i32, i32, i32) {
+ (self.state.into(), self.mode, self.size, self.mtime)
+ }
+
+ pub fn mtime_is_ambiguous(&self, now: i32) -> bool {
+ self.state == EntryState::Normal && self.mtime == now
+ }
+
+ pub fn clear_ambiguous_mtime(&mut self, now: i32) -> bool {
+ let ambiguous = self.mtime_is_ambiguous(now);
+ if ambiguous {
+ // The file was last modified "simultaneously" with the current
+ // write to dirstate (i.e. within the same second for file-
+ // systems with a granularity of 1 sec). This commonly happens
+ // for at least a couple of files on 'update'.
+ // The user could change the file without changing its size
+ // within the same second. Invalidate the file's mtime in
+ // dirstate, forcing future 'status' calls to compare the
+ // contents of the file if the size is the same. This prevents
+ // mistakenly treating such files as clean.
+ self.clear_mtime()
+ }
+ ambiguous
+ }
+
+ pub fn clear_mtime(&mut self) {
+ self.mtime = -1;
+ }
+}
+
+impl EntryState {
+ pub fn is_tracked(self) -> bool {
+ use EntryState::*;
+ match self {
+ Normal | Added | Merged => true,
+ Removed | Unknown => false,
+ }
+ }
+}
+
+impl TryFrom<u8> for EntryState {
+ type Error = HgError;
+
+ fn try_from(value: u8) -> Result<Self, Self::Error> {
+ match value {
+ b'n' => Ok(EntryState::Normal),
+ b'a' => Ok(EntryState::Added),
+ b'r' => Ok(EntryState::Removed),
+ b'm' => Ok(EntryState::Merged),
+ b'?' => Ok(EntryState::Unknown),
+ _ => Err(HgError::CorruptedRepository(format!(
+ "Incorrect dirstate entry state {}",
+ value
+ ))),
+ }
+ }
+}
+
+impl Into<u8> for EntryState {
+ fn into(self) -> u8 {
+ match self {
+ EntryState::Normal => b'n',
+ EntryState::Added => b'a',
+ EntryState::Removed => b'r',
+ EntryState::Merged => b'm',
+ EntryState::Unknown => b'?',
+ }
+ }
+}
--- a/rust/hg-core/src/dirstate/parsers.rs Mon Sep 20 14:21:18 2021 -0400
+++ b/rust/hg-core/src/dirstate/parsers.rs Fri Sep 17 12:42:24 2021 +0200
@@ -6,11 +6,11 @@
use crate::errors::HgError;
use crate::utils::hg_path::HgPath;
use crate::{
- dirstate::{CopyMap, EntryState, RawEntry, StateMap},
+ dirstate::{CopyMap, EntryState, StateMap},
DirstateEntry, DirstateParents,
};
use byteorder::{BigEndian, WriteBytesExt};
-use bytes_cast::BytesCast;
+use bytes_cast::{unaligned, BytesCast};
use micro_timer::timed;
use std::convert::{TryFrom, TryInto};
@@ -48,6 +48,16 @@
Ok((parents, entries, copies))
}
+#[derive(BytesCast)]
+#[repr(C)]
+pub(super) struct RawEntry {
+ state: u8,
+ mode: unaligned::I32Be,
+ size: unaligned::I32Be,
+ mtime: unaligned::I32Be,
+ length: unaligned::I32Be,
+}
+
pub fn parse_dirstate_entries<'a>(
mut contents: &'a [u8],
mut each_entry: impl FnMut(
@@ -131,33 +141,6 @@
/// Seconds since the Unix epoch
pub struct Timestamp(pub i64);
-impl DirstateEntry {
- pub fn mtime_is_ambiguous(&self, now: i32) -> bool {
- self.state == EntryState::Normal && self.mtime == now
- }
-
- pub fn clear_ambiguous_mtime(&mut self, now: i32) -> bool {
- let ambiguous = self.mtime_is_ambiguous(now);
- if ambiguous {
- // The file was last modified "simultaneously" with the current
- // write to dirstate (i.e. within the same second for file-
- // systems with a granularity of 1 sec). This commonly happens
- // for at least a couple of files on 'update'.
- // The user could change the file without changing its size
- // within the same second. Invalidate the file's mtime in
- // dirstate, forcing future 'status' calls to compare the
- // contents of the file if the size is the same. This prevents
- // mistakenly treating such files as clean.
- self.clear_mtime()
- }
- ambiguous
- }
-
- pub fn clear_mtime(&mut self) {
- self.mtime = -1;
- }
-}
-
pub fn pack_dirstate(
state_map: &mut StateMap,
copy_map: &CopyMap,