diff --git a/mercurial/cext/util.h b/mercurial/cext/util.h --- a/mercurial/cext/util.h +++ b/mercurial/cext/util.h @@ -40,6 +40,8 @@ static const int dirstate_flag_mode_exec_perm = 1 << 6; static const int dirstate_flag_mode_is_symlink = 1 << 7; static const int dirstate_flag_expected_state_is_modified = 1 << 8; +static const int dirstate_flag_unrecorded_unknown = 1 << 9; +static const int dirstate_flag_unrecorded_ignored = 1 << 10; extern PyTypeObject dirstateItemType; #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType) diff --git a/mercurial/dirstateutils/v2.py b/mercurial/dirstateutils/v2.py --- a/mercurial/dirstateutils/v2.py +++ b/mercurial/dirstateutils/v2.py @@ -81,6 +81,9 @@ """parse nodes from starting at offset This is used by parse_dirstate to recursively fill `map` and `copy_map`. + + All directory specific information is ignored and do not need any + processing (HAS_DIRECTORY_MTIME, UNRECORDED_UNKNOWN, UNRECORDED_IGNORED) """ for i in range(len): node_start = start + NODE_SIZE * i diff --git a/mercurial/helptext/internals/dirstate-v2.txt b/mercurial/helptext/internals/dirstate-v2.txt --- a/mercurial/helptext/internals/dirstate-v2.txt +++ b/mercurial/helptext/internals/dirstate-v2.txt @@ -384,6 +384,8 @@ MODE_EXEC_PERM = 1 << 6 MODE_IS_SYMLINK = 1 << 7 EXPECTED_STATE_IS_MODIFIED = 1 << 8 + UNRECORDED_UNKNOWN = 1 << 9 + UNRECORDED_UNKNOWN = 1 << 10 The meaning of each bit is described below. @@ -530,3 +532,15 @@ does not need to do the same again. It is valid to never set this bit, and consider expected metadata ambiguous if it is set. + +`UNRECORDED_UNKNOWN` + The node might have unknown children on disk that are not recorded as + children-nodes of this node. If this flag is set and the current operation + need to list the unknown files, the optimization from `HAS_DIRECTORY_MTIME` + cannot be used. + +`UNRECORDED_IGNORED` + The node might have ignored children on disk that are not recorded as + children-nodes of this node. If this flag is set and the current operation + need to list the ignored files, the optimization from `HAS_DIRECTORY_MTIME` + cannot be used. diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -54,6 +54,8 @@ DIRSTATE_V2_MODE_EXEC_PERM = 1 << 6 DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 7 DIRSTATE_V2_EXPECTED_STATE_IS_MODIFIED = 1 << 8 +DIRSTATE_V2_UNRECORDED_UNKNOWN = 1 << 9 +DIRSTATE_V2_UNRECORDED_IGNORED = 1 << 10 @attr.s(slots=True, init=False) @@ -340,6 +342,9 @@ flags |= DIRSTATE_V2_MODE_IS_SYMLINK if self._mtime is not None: flags |= DIRSTATE_V2_HAS_FILE_MTIME + # Note: we do not need to do anything regarding + # DIRSTATE_V2_UNRECORDED_UNKNOWN and DIRSTATE_V2_UNRECORDED_IGNORED + # since we never set _DIRSTATE_V2_HAS_DIRCTORY_MTIME return (flags, self._size or 0, self._mtime or 0) def v1_state(self): 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 @@ -111,6 +111,8 @@ const MODE_EXEC_PERM = 1 << 6; const MODE_IS_SYMLINK = 1 << 7; const EXPECTED_STATE_IS_MODIFIED = 1 << 8; + const UNRECORDED_UNKNOWN = 1 << 9; + const UNRECORDED_IGNORED = 1 << 10; } } @@ -322,7 +324,11 @@ pub(super) fn cached_directory_mtime( &self, ) -> Result, DirstateV2ParseError> { - if self.flags().contains(Flags::HAS_DIRECTORY_MTIME) { + // For now we do not have code to handle UNRECORDED_UNKNOWN, so we + // ignore the mtime if the flag is set. + if self.flags().contains(Flags::HAS_DIRECTORY_MTIME) + && !self.flags().contains(Flags::UNRECORDED_UNKNOWN) + { if self.flags().contains(Flags::HAS_FILE_MTIME) { Err(DirstateV2ParseError) } else { @@ -589,7 +595,14 @@ Node::from_dirstate_entry(entry) } dirstate_map::NodeData::CachedDirectory { mtime } => ( - Flags::HAS_DIRECTORY_MTIME, + // we currently never record ignored files so we + // blindly set UNRECORDED_IGNORED,. We don't need + // to set + // UNRECORDED_UNKNOWN since we currently never set + // HAS_DIRECTORY_MTIME + // if unknow files were present. + Flags::HAS_DIRECTORY_MTIME + | Flags::UNRECORDED_IGNORED, 0.into(), (*mtime).into(), ),