Patchwork D11688: dirstate-v2: preserve the fallback values on disk

login
register
mail settings
Submitter phabricator
Date Oct. 19, 2021, 1:21 a.m.
Message ID <differential-rev-PHID-DREV-7tmbxojcqwwiy6c6zqil-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50010/
State Superseded
Headers show

Comments

phabricator - Oct. 19, 2021, 1:21 a.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  When the fallback values are set, they are now read and written to disk.
  
  See format documentation for details.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11688

AFFECTED FILES
  mercurial/helptext/internals/dirstate-v2.txt
  mercurial/pure/parsers.py
  rust/hg-core/src/dirstate/entry.rs
  rust/hg-core/src/dirstate_tree/on_disk.rs

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

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
@@ -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)
     }
 }
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
@@ -341,7 +341,15 @@ 
     /// Returns `(wdir_tracked, p1_tracked, p2_info, mode_size, mtime)`
     pub(crate) fn v2_data(
         &self,
-    ) -> (bool, bool, bool, Option<(u32, u32)>, Option<u32>) {
+    ) -> (
+        bool,
+        bool,
+        bool,
+        Option<(u32, u32)>,
+        Option<u32>,
+        Option<bool>,
+        Option<bool>,
+    ) {
         if !self.any_tracked() {
             // TODO: return an Option instead?
             panic!("Accessing v1_state of an untracked DirstateEntry")
@@ -351,7 +359,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 --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py
--- a/mercurial/pure/parsers.py
+++ b/mercurial/pure/parsers.py
@@ -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
@@ -422,6 +436,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 --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
@@ -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 carry as "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 carry as "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.