# HG changeset patch # User Pierre-Yves David # Date 1634547414 -7200 # Node ID b874e8d81a989159f47701953df1ac87710f16a6 # Parent 948570aa763059eb29bd2a65538e3255a158aa0a dirstate-v2: preserve the fallback values on disk When the fallback values are set, they are now read and written to disk. See format documentation for details. Differential Revision: https://phab.mercurial-scm.org/D11688 diff -r 948570aa7630 -r b874e8d81a98 mercurial/helptext/internals/dirstate-v2.txt --- a/mercurial/helptext/internals/dirstate-v2.txt Mon Oct 18 20:02:05 2021 +0200 +++ b/mercurial/helptext/internals/dirstate-v2.txt Mon Oct 18 10:56:54 2021 +0200 @@ -386,6 +386,10 @@ EXPECTED_STATE_IS_MODIFIED = 1 << 8 ALL_UNKNOWN_RECORDED = 1 << 9 ALL_IGNORED_RECORDED = 1 << 10 + HAS_FALLBACK_EXEC = 1 << 11 + FALLBACK_EXEC = 1 << 12 + HAS_FALLBACK_SYMLINK = 1 << 13 + FALLBACK_SYMLINK = 1 << 14 The meaning of each bit is described below. @@ -558,3 +562,33 @@ Also note that having this flag unset does not imply that no "ignored" children have been recorded. Some might be present, but there is no garantee that is will be all of them. + +`HAS_FALLBACK_EXEC` + If this flag is set, the entry carries "fallback" information for the + executable bit in the `FALLBACK_EXEC` flag. + + Fallback information can be stored in the dirstate to keep track of + filesystem attribute tracked by Mercurial when the underlying file + system or operating system does not support that property, (e.g. + Windows). + +`FALLBACK_EXEC` + Should be ignored if `HAS_FALLBACK_EXEC` is unset. If set the file for this + entry should be considered executable if that information cannot be + extracted from the file system. If unset it should be considered + non-executable instead. + +`HAS_FALLBACK_SYMLINK` + If this flag is set, the entry carries "fallback" information for symbolic + link status in the `FALLBACK_SYMLINK` flag. + + Fallback information can be stored in the dirstate to keep track of + filesystem attribute tracked by Mercurial when the underlying file + system or operating system does not support that property, (e.g. + Windows). + +`FALLBACK_SYMLINK` + Should be ignored if `HAS_FALLBACK_SYMLINK` is unset. If set the file for + this entry should be considered a symlink if that information cannot be + extracted from the file system. If unset it should be considered a normal + file instead. diff -r 948570aa7630 -r b874e8d81a98 mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py Mon Oct 18 20:02:05 2021 +0200 +++ b/mercurial/pure/parsers.py Mon Oct 18 10:56:54 2021 +0200 @@ -56,6 +56,10 @@ DIRSTATE_V2_EXPECTED_STATE_IS_MODIFIED = 1 << 8 DIRSTATE_V2_ALL_UNKNOWN_RECORDED = 1 << 9 DIRSTATE_V2_ALL_IGNORED_RECORDED = 1 << 10 +DIRSTATE_V2_HAS_FALLBACK_EXEC = 1 << 11 +DIRSTATE_V2_FALLBACK_EXEC = 1 << 12 +DIRSTATE_V2_HAS_FALLBACK_SYMLINK = 1 << 13 +DIRSTATE_V2_FALLBACK_SYMLINK = 1 << 14 @attr.s(slots=True, init=False) @@ -142,6 +146,14 @@ has_mode_size = False has_meaningful_mtime = False + fallback_exec = None + if flags & DIRSTATE_V2_HAS_FALLBACK_EXEC: + fallback_exec = flags & DIRSTATE_V2_FALLBACK_EXEC + + fallback_symlink = None + if flags & DIRSTATE_V2_HAS_FALLBACK_SYMLINK: + fallback_symlink = flags & DIRSTATE_V2_FALLBACK_SYMLINK + if has_mode_size: assert stat.S_IXUSR == 0o100 if flags & DIRSTATE_V2_MODE_EXEC_PERM: @@ -159,6 +171,8 @@ has_meaningful_data=has_mode_size, has_meaningful_mtime=has_meaningful_mtime, parentfiledata=(mode, size, mtime), + fallback_exec=fallback_exec, + fallback_symlink=fallback_symlink, ) @classmethod @@ -428,6 +442,17 @@ flags |= DIRSTATE_V2_MODE_IS_SYMLINK if self._mtime is not None: flags |= DIRSTATE_V2_HAS_FILE_MTIME + + if self._fallback_exec is not None: + flags |= DIRSTATE_V2_HAS_FALLBACK_EXEC + if self._fallback_exec: + flags |= DIRSTATE_V2_FALLBACK_EXEC + + if self._fallback_symlink is not None: + flags |= DIRSTATE_V2_HAS_FALLBACK_SYMLINK + if self._fallback_symlink: + flags |= DIRSTATE_V2_FALLBACK_SYMLINK + # Note: we do not need to do anything regarding # DIRSTATE_V2_ALL_UNKNOWN_RECORDED and DIRSTATE_V2_ALL_IGNORED_RECORDED # since we never set _DIRSTATE_V2_HAS_DIRCTORY_MTIME diff -r 948570aa7630 -r b874e8d81a98 rust/hg-core/src/dirstate/entry.rs --- a/rust/hg-core/src/dirstate/entry.rs Mon Oct 18 20:02:05 2021 +0200 +++ b/rust/hg-core/src/dirstate/entry.rs Mon Oct 18 10:56:54 2021 +0200 @@ -339,7 +339,15 @@ /// Returns `(wdir_tracked, p1_tracked, p2_info, mode_size, mtime)` pub(crate) fn v2_data( &self, - ) -> (bool, bool, bool, Option<(u32, u32)>, Option) { + ) -> ( + bool, + bool, + bool, + Option<(u32, u32)>, + Option, + Option, + Option, + ) { if !self.any_tracked() { // TODO: return an Option instead? panic!("Accessing v1_state of an untracked DirstateEntry") @@ -349,7 +357,15 @@ let p2_info = self.flags.contains(Flags::P2_INFO); let mode_size = self.mode_size; let mtime = self.mtime; - (wdir_tracked, p1_tracked, p2_info, mode_size, mtime) + ( + wdir_tracked, + p1_tracked, + p2_info, + mode_size, + mtime, + self.get_fallback_exec(), + self.get_fallback_symlink(), + ) } fn v1_state(&self) -> EntryState { diff -r 948570aa7630 -r b874e8d81a98 rust/hg-core/src/dirstate_tree/on_disk.rs --- a/rust/hg-core/src/dirstate_tree/on_disk.rs Mon Oct 18 20:02:05 2021 +0200 +++ b/rust/hg-core/src/dirstate_tree/on_disk.rs Mon Oct 18 10:56:54 2021 +0200 @@ -113,6 +113,10 @@ const EXPECTED_STATE_IS_MODIFIED = 1 << 8; const ALL_UNKNOWN_RECORDED = 1 << 9; const ALL_IGNORED_RECORDED = 1 << 10; + const HAS_FALLBACK_EXEC = 1 << 11; + const FALLBACK_EXEC = 1 << 12; + const HAS_FALLBACK_SYMLINK = 1 << 13; + const FALLBACK_SYMLINK = 1 << 14; } } @@ -420,8 +424,15 @@ fn from_dirstate_entry( entry: &DirstateEntry, ) -> (Flags, U32Be, PackedTruncatedTimestamp) { - let (wdir_tracked, p1_tracked, p2_info, mode_size_opt, mtime_opt) = - entry.v2_data(); + let ( + wdir_tracked, + p1_tracked, + p2_info, + mode_size_opt, + mtime_opt, + fallback_exec, + fallback_symlink, + ) = entry.v2_data(); // TODO: convert throug raw flag bits instead? let mut flags = Flags::empty(); flags.set(Flags::WDIR_TRACKED, wdir_tracked); @@ -446,6 +457,18 @@ } else { PackedTruncatedTimestamp::null() }; + if let Some(f_exec) = fallback_exec { + flags.insert(Flags::HAS_FALLBACK_EXEC); + if f_exec { + flags.insert(Flags::FALLBACK_EXEC); + } + } + if let Some(f_symlink) = fallback_symlink { + flags.insert(Flags::HAS_FALLBACK_SYMLINK); + if f_symlink { + flags.insert(Flags::FALLBACK_SYMLINK); + } + } (flags, size, mtime) } }